[lld] r215544 - [AArch64] Initial ELF/AArch64 Support
Chad Rosier
mcrosier at codeaurora.org
Wed Aug 13 06:16:38 PDT 2014
Author: mcrosier
Date: Wed Aug 13 08:16:38 2014
New Revision: 215544
URL: http://llvm.org/viewvc/llvm-project?rev=215544&view=rev
Log:
[AArch64] Initial ELF/AArch64 Support
This patch adds the initial ELF/AArch64 support to lld. Only a basic "Hello
World" app has been successfully tested for both dynamic and static compiling.
Differential Revision: http://reviews.llvm.org/D4778
Patch by Daniel Stewart <stewartd at codeaurora.org>!
Added:
lld/trunk/lib/ReaderWriter/ELF/AArch64/
lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h
lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h
lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp
lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h
lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp
lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h
lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp
lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.h
lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64Target.h
lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp
lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h
lld/trunk/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt
lld/trunk/lib/ReaderWriter/ELF/AArch64/Makefile
lld/trunk/lib/ReaderWriter/ELF/AArch64/TODO.rst
lld/trunk/test/elf/AArch64/
lld/trunk/test/elf/AArch64/Inputs/
lld/trunk/test/elf/AArch64/Inputs/fn.c
lld/trunk/test/elf/AArch64/Inputs/fn.o
lld/trunk/test/elf/AArch64/Inputs/initfini-option.c
lld/trunk/test/elf/AArch64/Inputs/initfini-option.o
lld/trunk/test/elf/AArch64/Inputs/initfini.c
lld/trunk/test/elf/AArch64/Inputs/initfini.o
lld/trunk/test/elf/AArch64/Inputs/main.c
lld/trunk/test/elf/AArch64/Inputs/main.o
lld/trunk/test/elf/AArch64/Inputs/no-interp-section.c
lld/trunk/test/elf/AArch64/Inputs/no-interp-section.o
lld/trunk/test/elf/AArch64/Inputs/zerosizedsection.o
lld/trunk/test/elf/AArch64/Inputs/zerosizedsection.s
lld/trunk/test/elf/AArch64/defsym.test
lld/trunk/test/elf/AArch64/dontignorezerosize-sections.test
lld/trunk/test/elf/AArch64/dynlib-nointerp-section.test
lld/trunk/test/elf/AArch64/initfini-alignment.test
lld/trunk/test/elf/AArch64/initfini-option.test
lld/trunk/test/elf/AArch64/initfini.test
Modified:
lld/trunk/docs/open_projects.rst
lld/trunk/include/lld/Core/Reference.h
lld/trunk/lib/Driver/GnuLdDriver.cpp
lld/trunk/lib/ReaderWriter/ELF/Atoms.h
lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt
lld/trunk/lib/ReaderWriter/ELF/ELFFile.h
lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
lld/trunk/lib/ReaderWriter/ELF/Makefile
lld/trunk/lib/ReaderWriter/ELF/Targets.h
lld/trunk/tools/lld/Makefile
lld/trunk/unittests/DriverTests/Makefile
Modified: lld/trunk/docs/open_projects.rst
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/docs/open_projects.rst?rev=215544&r1=215543&r2=215544&view=diff
==============================================================================
--- lld/trunk/docs/open_projects.rst (original)
+++ lld/trunk/docs/open_projects.rst Wed Aug 13 08:16:38 2014
@@ -7,6 +7,7 @@ Open Projects
.. include:: ../lib/Core/TODO.txt
.. include:: ../lib/Driver/TODO.rst
.. include:: ../lib/ReaderWriter/ELF/X86_64/TODO.rst
+.. include:: ../lib/ReaderWriter/ELF/AArch64/TODO.rst
.. include:: ../tools/lld/TODO.txt
Documentation TODOs
Modified: lld/trunk/include/lld/Core/Reference.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Reference.h?rev=215544&r1=215543&r2=215544&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Reference.h (original)
+++ lld/trunk/include/lld/Core/Reference.h Wed Aug 13 08:16:38 2014
@@ -64,7 +64,8 @@ public:
ARM = 3,
PowerPC = 4,
Hexagon = 5,
- Mips = 6
+ Mips = 6,
+ AArch64 = 7
};
KindArch kindArch() const { return (KindArch)_kindArch; }
Modified: lld/trunk/lib/Driver/GnuLdDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdDriver.cpp?rev=215544&r1=215543&r2=215544&view=diff
==============================================================================
--- lld/trunk/lib/Driver/GnuLdDriver.cpp (original)
+++ lld/trunk/lib/Driver/GnuLdDriver.cpp Wed Aug 13 08:16:38 2014
@@ -204,6 +204,10 @@ getArchType(const llvm::Triple &triple,
if (value == "elf32ltsmip")
return llvm::Triple::mipsel;
return llvm::None;
+ case llvm::Triple::aarch64:
+ if (value == "aarch64linux")
+ return llvm::Triple::aarch64;
+ return llvm::None;
default:
return llvm::None;
}
Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h Wed Aug 13 08:16:38 2014
@@ -0,0 +1,69 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h ---------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef AARCH64_DYNAMIC_LIBRARY_WRITER_H
+#define AARCH64_DYNAMIC_LIBRARY_WRITER_H
+
+#include "DynamicLibraryWriter.h"
+#include "AArch64LinkingContext.h"
+
+namespace lld {
+namespace elf {
+
+template <class ELFT>
+class AArch64DynamicLibraryWriter : public DynamicLibraryWriter<ELFT> {
+public:
+ AArch64DynamicLibraryWriter(AArch64LinkingContext &context,
+ AArch64TargetLayout<ELFT> &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<ELFT>::finalizeDefaultAtomValues();
+ }
+
+ virtual void addDefaultAtoms() {
+ return DynamicLibraryWriter<ELFT>::addDefaultAtoms();
+ }
+
+private:
+ class GOTFile : public SimpleFile {
+ public:
+ GOTFile(const ELFLinkingContext &eti) : SimpleFile("GOTFile") {}
+ llvm::BumpPtrAllocator _alloc;
+ };
+
+ std::unique_ptr<GOTFile> _gotFile;
+ AArch64LinkingContext &_context;
+ AArch64TargetLayout<ELFT> &_AArch64Layout;
+};
+
+template <class ELFT>
+AArch64DynamicLibraryWriter<ELFT>::AArch64DynamicLibraryWriter(
+ AArch64LinkingContext &context, AArch64TargetLayout<ELFT> &layout)
+ : DynamicLibraryWriter<ELFT>(context, layout),
+ _gotFile(new GOTFile(context)), _context(context),
+ _AArch64Layout(layout) {}
+
+template <class ELFT>
+bool AArch64DynamicLibraryWriter<ELFT>::createImplicitFiles(
+ std::vector<std::unique_ptr<File>> &result) {
+ DynamicLibraryWriter<ELFT>::createImplicitFiles(result);
+ _gotFile->addAtom(*new (_gotFile->_alloc) GLOBAL_OFFSET_TABLEAtom(*_gotFile));
+ _gotFile->addAtom(*new (_gotFile->_alloc) TLSGETADDRAtom(*_gotFile));
+ _gotFile->addAtom(*new (_gotFile->_alloc) DYNAMICAtom(*_gotFile));
+ result.push_back(std::move(_gotFile));
+ return true;
+}
+
+} // namespace elf
+} // namespace lld
+
+#endif
Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h Wed Aug 13 08:16:38 2014
@@ -0,0 +1,69 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h -------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef AARCH64_EXECUTABLE_WRITER_H
+#define AARCH64_EXECUTABLE_WRITER_H
+
+#include "ExecutableWriter.h"
+#include "AArch64LinkingContext.h"
+
+namespace lld {
+namespace elf {
+
+template <class ELFT>
+class AArch64ExecutableWriter : public ExecutableWriter<ELFT> {
+public:
+ AArch64ExecutableWriter(AArch64LinkingContext &context,
+ AArch64TargetLayout<ELFT> &layout);
+
+protected:
+ // Add any runtime files and their atoms to the output
+ bool createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
+
+ void finalizeDefaultAtomValues() override {
+ return ExecutableWriter<ELFT>::finalizeDefaultAtomValues();
+ }
+
+ void addDefaultAtoms() override{
+ return ExecutableWriter<ELFT>::addDefaultAtoms();
+ }
+
+private:
+ class GOTFile : public SimpleFile {
+ public:
+ GOTFile(const ELFLinkingContext &eti) : SimpleFile("GOTFile") {}
+ llvm::BumpPtrAllocator _alloc;
+ };
+
+ std::unique_ptr<GOTFile> _gotFile;
+ AArch64LinkingContext &_context;
+ AArch64TargetLayout<ELFT> &_AArch64Layout;
+};
+
+template <class ELFT>
+AArch64ExecutableWriter<ELFT>::AArch64ExecutableWriter(
+ AArch64LinkingContext &context, AArch64TargetLayout<ELFT> &layout)
+ : ExecutableWriter<ELFT>(context, layout), _gotFile(new GOTFile(context)),
+ _context(context), _AArch64Layout(layout) {}
+
+template <class ELFT>
+bool AArch64ExecutableWriter<ELFT>::createImplicitFiles(
+ std::vector<std::unique_ptr<File>> &result) {
+ ExecutableWriter<ELFT>::createImplicitFiles(result);
+ _gotFile->addAtom(*new (_gotFile->_alloc) GLOBAL_OFFSET_TABLEAtom(*_gotFile));
+ _gotFile->addAtom(*new (_gotFile->_alloc) TLSGETADDRAtom(*_gotFile));
+ if (_context.isDynamic())
+ _gotFile->addAtom(*new (_gotFile->_alloc) DYNAMICAtom(*_gotFile));
+ result.push_back(std::move(_gotFile));
+ return true;
+}
+
+} // namespace elf
+} // namespace lld
+
+#endif
Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp Wed Aug 13 08:16:38 2014
@@ -0,0 +1,112 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp -------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AArch64LinkingContext.h"
+
+#include "lld/Core/File.h"
+#include "lld/Core/Instrumentation.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringSwitch.h"
+
+#include "Atoms.h"
+#include "AArch64RelocationPass.h"
+
+using namespace lld;
+using namespace lld::elf;
+
+using llvm::makeArrayRef;
+
+namespace {
+using namespace llvm::ELF;
+
+const uint8_t AArch64InitFiniAtomContent[8] = {0};
+
+// AArch64InitFini Atom
+class AArch64InitAtom : public InitFiniAtom {
+public:
+ AArch64InitAtom(const File &f, StringRef function)
+ : InitFiniAtom(f, ".init_array") {
+#ifndef NDEBUG
+ _name = "__init_fn_";
+ _name += function;
+#endif
+ }
+ ArrayRef<uint8_t> rawContent() const override {
+ return makeArrayRef(AArch64InitFiniAtomContent);
+ }
+ Alignment alignment() const override { return Alignment(3); }
+};
+
+class AArch64FiniAtom : public InitFiniAtom {
+public:
+ AArch64FiniAtom(const File &f, StringRef function)
+ : InitFiniAtom(f, ".fini_array") {
+#ifndef NDEBUG
+ _name = "__fini_fn_";
+ _name += function;
+#endif
+ }
+ ArrayRef<uint8_t> rawContent() const override {
+ return makeArrayRef(AArch64InitFiniAtomContent);
+ }
+
+ Alignment alignment() const override { return Alignment(3); }
+};
+
+class AArch64InitFiniFile : public SimpleFile {
+public:
+ AArch64InitFiniFile(const ELFLinkingContext &context)
+ : SimpleFile("command line option -init/-fini"), _ordinal(0) {}
+
+ void addInitFunction(StringRef name) {
+ Atom *initFunctionAtom = new (_allocator) SimpleUndefinedAtom(*this, name);
+ AArch64InitAtom *initAtom = (new (_allocator) AArch64InitAtom(*this, name));
+ initAtom->addReferenceELF_AArch64(llvm::ELF::R_AARCH64_ABS64, 0,
+ initFunctionAtom, 0);
+ initAtom->setOrdinal(_ordinal++);
+ addAtom(*initFunctionAtom);
+ addAtom(*initAtom);
+ }
+
+ void addFiniFunction(StringRef name) {
+ Atom *finiFunctionAtom = new (_allocator) SimpleUndefinedAtom(*this, name);
+ AArch64FiniAtom *finiAtom = (new (_allocator) AArch64FiniAtom(*this, name));
+ finiAtom->addReferenceELF_AArch64(llvm::ELF::R_AARCH64_ABS64, 0,
+ finiFunctionAtom, 0);
+ finiAtom->setOrdinal(_ordinal++);
+ addAtom(*finiFunctionAtom);
+ addAtom(*finiAtom);
+ }
+
+private:
+ llvm::BumpPtrAllocator _allocator;
+ uint64_t _ordinal;
+};
+
+} // end anon namespace
+
+void elf::AArch64LinkingContext::addPasses(PassManager &pm) {
+ auto pass = createAArch64RelocationPass(*this);
+ if (pass)
+ pm.add(std::move(pass));
+ ELFLinkingContext::addPasses(pm);
+}
+
+void elf::AArch64LinkingContext::createInternalFiles(
+ std::vector<std::unique_ptr<File>> &result) const {
+ ELFLinkingContext::createInternalFiles(result);
+ std::unique_ptr<AArch64InitFiniFile> initFiniFile(
+ new AArch64InitFiniFile(*this));
+ for (auto ai : initFunctions())
+ initFiniFile->addInitFunction(ai);
+ for (auto ai : finiFunctions())
+ initFiniFile->addFiniFunction(ai);
+ result.push_back(std::move(initFiniFile));
+}
Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h Wed Aug 13 08:16:38 2014
@@ -0,0 +1,95 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.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_AARCH64_AARCH64_LINKING_CONTEXT_H
+#define LLD_READER_WRITER_ELF_AARCH64_AARCH64_LINKING_CONTEXT_H
+
+#include "AArch64TargetHandler.h"
+
+#include "lld/ReaderWriter/ELFLinkingContext.h"
+
+#include "llvm/Object/ELF.h"
+#include "llvm/Support/ELF.h"
+
+namespace lld {
+namespace elf {
+
+enum {
+ /// \brief The offset to add operation for a R_AARCH64_ADR_GOT_PAGE
+ ADD_AARCH64_GOTRELINDEX = 0xE000,
+};
+
+class AArch64LinkingContext final : public ELFLinkingContext {
+public:
+ AArch64LinkingContext(llvm::Triple triple)
+ : ELFLinkingContext(triple, std::unique_ptr<TargetHandlerBase>(
+ new AArch64TargetHandler(*this))) {}
+
+ void addPasses(PassManager &) override;
+
+ uint64_t getBaseAddress() const override {
+ if (_baseAddress == 0)
+ return 0x400000;
+ return _baseAddress;
+ }
+
+ bool isDynamicRelocation(const DefinedAtom &,
+ const Reference &r) const override {
+ if (r.kindNamespace() != Reference::KindNamespace::ELF)
+ return false;
+ assert(r.kindArch() == Reference::KindArch::AArch64);
+ switch (r.kindValue()) {
+ case llvm::ELF::R_AARCH64_COPY:
+ case llvm::ELF::R_AARCH64_GLOB_DAT:
+ case llvm::ELF::R_AARCH64_RELATIVE:
+ case llvm::ELF::R_AARCH64_TLS_DTPREL64:
+ case llvm::ELF::R_AARCH64_TLS_DTPMOD64:
+ case llvm::ELF::R_AARCH64_TLS_TPREL64:
+ case llvm::ELF::R_AARCH64_TLSDESC:
+ case llvm::ELF::R_AARCH64_IRELATIVE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ bool isPLTRelocation(const DefinedAtom &,
+ const Reference &r) const override {
+ if (r.kindNamespace() != Reference::KindNamespace::ELF)
+ return false;
+ assert(r.kindArch() == Reference::KindArch::AArch64);
+ switch (r.kindValue()) {
+ case llvm::ELF::R_AARCH64_JUMP_SLOT:
+ case llvm::ELF::R_AARCH64_IRELATIVE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ bool isRelativeReloc(const Reference &r) const override {
+ if (r.kindNamespace() != Reference::KindNamespace::ELF)
+ return false;
+ assert(r.kindArch() == Reference::KindArch::AArch64);
+ switch (r.kindValue()) {
+ case llvm::ELF::R_AARCH64_IRELATIVE:
+ case llvm::ELF::R_AARCH64_RELATIVE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /// \brief Create Internal files for Init/Fini
+ void createInternalFiles(std::vector<std::unique_ptr<File>> &) const override;
+};
+} // end namespace elf
+} // end namespace lld
+
+#endif
Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp Wed Aug 13 08:16:38 2014
@@ -0,0 +1,490 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp ----------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AArch64TargetHandler.h"
+#include "AArch64LinkingContext.h"
+#include "llvm/Support/Debug.h"
+
+using namespace lld;
+using namespace elf;
+
+#define PAGE(X) ((X) & ~0x0FFFL)
+
+/// \brief R_AARCH64_ABS64 - word64: S + A
+static void relocR_AARCH64_ABS64(uint8_t *location, uint64_t P, uint64_t S,
+ int64_t A) {
+ int64_t result = (int64_t)S + A;
+ DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+ llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
+ llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
+ llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
+ llvm::dbgs() << " result: 0x" << Twine::utohexstr(result)
+ << "\n");
+ *reinterpret_cast<llvm::support::ulittle64_t *>(location) =
+ result |
+ (int64_t) * reinterpret_cast<llvm::support::little64_t *>(location);
+}
+
+/// \brief R_AARCH64_PREL32 - word32: S + A - P
+static void relocR_AARCH64_PREL32(uint8_t *location, uint64_t P, uint64_t S,
+ int64_t A) {
+ int32_t result = (int32_t)((S + A) - P);
+ *reinterpret_cast<llvm::support::little32_t *>(location) =
+ result +
+ (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+/// \brief R_AARCH64_ABS32 - word32: S + A
+static void relocR_AARCH64_ABS32(uint8_t *location, uint64_t P, uint64_t S,
+ int64_t A) {
+ int32_t result = (int32_t)(S + A);
+ DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+ llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
+ llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
+ llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
+ llvm::dbgs() << " result: 0x" << Twine::utohexstr(result)
+ << "\n");
+ *reinterpret_cast<llvm::support::ulittle32_t *>(location) =
+ result |
+ (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+/// \brief R_AARCH64_ADR_PREL_PG_HI21 - Page(S+A) - Page(P)
+static void relocR_AARCH64_ADR_PREL_PG_HI21(uint8_t *location, uint64_t P,
+ uint64_t S, int64_t A) {
+ uint64_t result = (PAGE(S + A) - PAGE(P));
+ result = result >> 12;
+ uint32_t immlo = result & 0x3;
+ uint32_t immhi = result & 0x1FFFFC;
+ immlo = immlo << 29;
+ immhi = immhi << 3;
+ DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+ llvm::dbgs() << " S: " << Twine::utohexstr(S);
+ llvm::dbgs() << " A: " << Twine::utohexstr(A);
+ llvm::dbgs() << " P: " << Twine::utohexstr(P);
+ llvm::dbgs() << " immhi: " << Twine::utohexstr(immhi);
+ llvm::dbgs() << " immlo: " << Twine::utohexstr(immlo);
+ llvm::dbgs() << " result: " << Twine::utohexstr(result)
+ << "\n");
+ *reinterpret_cast<llvm::support::little32_t *>(location) =
+ immlo | immhi |
+ (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+ // TODO: Make sure this is correct!
+}
+
+/// \brief R_AARCH64_ADR_PREL_LO21 - S + A - P
+static void relocR_AARCH64_ADR_PREL_LO21(uint8_t *location, uint64_t P,
+ uint64_t S, int64_t A) {
+ uint64_t result = (S + A) - P;
+ uint32_t immlo = result & 0x3;
+ uint32_t immhi = result & 0x1FFFFC;
+ immlo = immlo << 29;
+ immhi = immhi << 3;
+ DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+ llvm::dbgs() << " S: " << Twine::utohexstr(S);
+ llvm::dbgs() << " A: " << Twine::utohexstr(A);
+ llvm::dbgs() << " P: " << Twine::utohexstr(P);
+ llvm::dbgs() << " immhi: " << Twine::utohexstr(immhi);
+ llvm::dbgs() << " immlo: " << Twine::utohexstr(immlo);
+ llvm::dbgs() << " result: " << Twine::utohexstr(result)
+ << "\n");
+ *reinterpret_cast<llvm::support::little32_t *>(location) =
+ immlo | immhi |
+ (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+ // TODO: Make sure this is correct!
+}
+
+/// \brief R_AARCH64_ADD_ABS_LO12_NC
+static void relocR_AARCH64_ADD_ABS_LO12_NC(uint8_t *location, uint64_t P,
+ uint64_t S, int64_t A) {
+ int32_t result = (int32_t)((S + A) & 0xFFF);
+ result <<= 10;
+ DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+ llvm::dbgs() << " S: " << Twine::utohexstr(S);
+ llvm::dbgs() << " A: " << Twine::utohexstr(A);
+ llvm::dbgs() << " P: " << Twine::utohexstr(P);
+ llvm::dbgs() << " result: " << Twine::utohexstr(result)
+ << "\n");
+ *reinterpret_cast<llvm::support::little32_t *>(location) =
+ result |
+ (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+static void relocJump26(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
+ int32_t result = (int32_t)((S + A) - P);
+ result &= 0x0FFFFFFC;
+ result >>= 2;
+ DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+ llvm::dbgs() << " S: " << Twine::utohexstr(S);
+ llvm::dbgs() << " A: " << Twine::utohexstr(A);
+ llvm::dbgs() << " P: " << Twine::utohexstr(P);
+ llvm::dbgs() << " result: " << Twine::utohexstr(result)
+ << "\n");
+ *reinterpret_cast<llvm::support::little32_t *>(location) =
+ result |
+ (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+/// \brief R_AARCH64_CONDBR19
+static void relocR_AARCH64_CONDBR19(uint8_t *location, uint64_t P, uint64_t S,
+ int64_t A) {
+ int32_t result = (int32_t)((S + A) - P);
+ result &= 0x01FFFFC;
+ result <<= 3;
+ DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+ llvm::dbgs() << " S: " << Twine::utohexstr(S);
+ llvm::dbgs() << " A: " << Twine::utohexstr(A);
+ llvm::dbgs() << " P: " << Twine::utohexstr(P);
+ llvm::dbgs() << " result: " << Twine::utohexstr(result)
+ << "\n");
+ *reinterpret_cast<llvm::support::little32_t *>(location) =
+ result |
+ (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+/// \brief R_AARCH64_LDST8_ABS_LO12_NC - S + A
+static void relocR_AARCH64_LDST8_ABS_LO12_NC(uint8_t *location, uint64_t P,
+ uint64_t S, int64_t A) {
+ int32_t result = (int32_t)((S + A) & 0xFFF);
+ result <<= 10;
+ DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+ llvm::dbgs() << " S: " << Twine::utohexstr(S);
+ llvm::dbgs() << " A: " << Twine::utohexstr(A);
+ llvm::dbgs() << " P: " << Twine::utohexstr(P);
+ llvm::dbgs() << " result: " << Twine::utohexstr(result)
+ << "\n");
+ *reinterpret_cast<llvm::support::little32_t *>(location) =
+ result |
+ (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+/// \brief R_AARCH64_LDST16_ABS_LO12_NC
+static void relocR_AARCH64_LDST16_ABS_LO12_NC(uint8_t *location, uint64_t P,
+ uint64_t S, int64_t A) {
+ int32_t result = (int32_t)(S + A);
+ result &= 0x0FFC;
+ result <<= 9;
+ DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+ llvm::dbgs() << " S: " << Twine::utohexstr(S);
+ llvm::dbgs() << " A: " << Twine::utohexstr(A);
+ llvm::dbgs() << " P: " << Twine::utohexstr(P);
+ llvm::dbgs() << " result: " << Twine::utohexstr(result)
+ << "\n");
+ *reinterpret_cast<llvm::support::little32_t *>(location) =
+ result |
+ (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+/// \brief R_AARCH64_LDST32_ABS_LO12_NC
+static void relocR_AARCH64_LDST32_ABS_LO12_NC(uint8_t *location, uint64_t P,
+ uint64_t S, int64_t A) {
+ int32_t result = (int32_t)(S + A);
+ result &= 0x0FFC;
+ result <<= 8;
+ DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+ llvm::dbgs() << " S: " << Twine::utohexstr(S);
+ llvm::dbgs() << " A: " << Twine::utohexstr(A);
+ llvm::dbgs() << " P: " << Twine::utohexstr(P);
+ llvm::dbgs() << " result: " << Twine::utohexstr(result)
+ << "\n");
+ *reinterpret_cast<llvm::support::little32_t *>(location) =
+ result |
+ (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+/// \brief R_AARCH64_LDST64_ABS_LO12_NC
+static void relocR_AARCH64_LDST64_ABS_LO12_NC(uint8_t *location, uint64_t P,
+ uint64_t S, int64_t A) {
+ int32_t result = (int32_t)(S + A);
+ result &= 0x0FF8;
+ result <<= 7;
+ DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+ llvm::dbgs() << " S: " << Twine::utohexstr(S);
+ llvm::dbgs() << " A: " << Twine::utohexstr(A);
+ llvm::dbgs() << " P: " << Twine::utohexstr(P);
+ llvm::dbgs() << " result: " << Twine::utohexstr(result)
+ << "\n");
+ *reinterpret_cast<llvm::support::little32_t *>(location) =
+ result |
+ (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+/// \brief R_AARCH64_LDST128_ABS_LO12_NC
+static void relocR_AARCH64_LDST128_ABS_LO12_NC(uint8_t *location, uint64_t P,
+ uint64_t S, int64_t A) {
+ int32_t result = (int32_t)(S + A);
+ result &= 0x0FF8;
+ result <<= 6;
+ DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+ llvm::dbgs() << " S: " << Twine::utohexstr(S);
+ llvm::dbgs() << " A: " << Twine::utohexstr(A);
+ llvm::dbgs() << " P: " << Twine::utohexstr(P);
+ llvm::dbgs() << " result: " << Twine::utohexstr(result)
+ << "\n");
+ *reinterpret_cast<llvm::support::little32_t *>(location) =
+ result |
+ (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+static void relocR_AARCH64_ADR_GOT_PAGE(uint8_t *location, uint64_t P,
+ uint64_t S, int64_t A) {
+ uint64_t result = PAGE(S + A) - PAGE(P);
+ result >>= 12;
+ uint32_t immlo = result & 0x3;
+ uint32_t immhi = result & 0x1FFFFC;
+ immlo = immlo << 29;
+ immhi = immhi << 3;
+ DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+ llvm::dbgs() << " S: " << Twine::utohexstr(S);
+ llvm::dbgs() << " A: " << Twine::utohexstr(A);
+ llvm::dbgs() << " P: " << Twine::utohexstr(P);
+ llvm::dbgs() << " immhi: " << Twine::utohexstr(immhi);
+ llvm::dbgs() << " immlo: " << Twine::utohexstr(immlo);
+ llvm::dbgs() << " result: " << Twine::utohexstr(result)
+ << "\n");
+ *reinterpret_cast<llvm::support::little32_t *>(location) =
+ immlo | immhi |
+ (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+// R_AARCH64_LD64_GOT_LO12_NC
+static void relocR_AARCH64_LD64_GOT_LO12_NC(uint8_t *location, uint64_t P,
+ uint64_t S, int64_t A) {
+ int32_t result = S + A;
+ DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+ llvm::dbgs() << " S: " << Twine::utohexstr(S);
+ llvm::dbgs() << " A: " << Twine::utohexstr(A);
+ llvm::dbgs() << " P: " << Twine::utohexstr(P);
+ llvm::dbgs() << " result: " << Twine::utohexstr(result)
+ << "\n");
+ result &= 0xFF8;
+ result <<= 7;
+ *reinterpret_cast<llvm::support::little32_t *>(location) =
+ result |
+ (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+// ADD_AARCH64_GOTRELINDEX
+static void relocADD_AARCH64_GOTRELINDEX(uint8_t *location, uint64_t P,
+ uint64_t S, int64_t A) {
+ int32_t result = S + A;
+ DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+ llvm::dbgs() << " S: " << Twine::utohexstr(S);
+ llvm::dbgs() << " A: " << Twine::utohexstr(A);
+ llvm::dbgs() << " P: " << Twine::utohexstr(P);
+ llvm::dbgs() << " result: " << Twine::utohexstr(result)
+ << "\n");
+ result &= 0xFFF;
+ result <<= 10;
+ *reinterpret_cast<llvm::support::little32_t *>(location) =
+ result |
+ (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+// R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21
+static void relocR_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21(uint8_t *location,
+ uint64_t P, uint64_t S,
+ int64_t A) {
+ int64_t result = PAGE(S + A) - PAGE(P);
+ result >>= 12;
+ uint32_t immlo = result & 0x3;
+ uint32_t immhi = result & 0x1FFFFC;
+ immlo = immlo << 29;
+ immhi = immhi << 3;
+ DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+ llvm::dbgs() << " S: " << Twine::utohexstr(S);
+ llvm::dbgs() << " A: " << Twine::utohexstr(A);
+ llvm::dbgs() << " P: " << Twine::utohexstr(P);
+ llvm::dbgs() << " immhi: " << Twine::utohexstr(immhi);
+ llvm::dbgs() << " immlo: " << Twine::utohexstr(immlo);
+ llvm::dbgs() << " result: " << Twine::utohexstr(result)
+ << "\n");
+ *reinterpret_cast<llvm::support::little32_t *>(location) =
+ immlo | immhi |
+ (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+// R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC
+static void relocR_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC(uint8_t *location,
+ uint64_t P, uint64_t S,
+ int64_t A) {
+ int32_t result = S + A;
+ result &= 0xFF8;
+ result <<= 7;
+ DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+ llvm::dbgs() << " S: " << Twine::utohexstr(S);
+ llvm::dbgs() << " A: " << Twine::utohexstr(A);
+ llvm::dbgs() << " P: " << Twine::utohexstr(P);
+ llvm::dbgs() << " result: " << Twine::utohexstr(result)
+ << "\n");
+ *reinterpret_cast<llvm::support::little32_t *>(location) =
+ result |
+ (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+/// \brief R_AARCH64_TLSLE_ADD_TPREL_HI12
+static void relocR_AARCH64_TLSLE_ADD_TPREL_HI12(uint8_t *location, uint64_t P,
+ uint64_t S, int64_t A) {
+ int32_t result = S + A;
+ result &= 0x0FFF000;
+ result >>= 2;
+ DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+ llvm::dbgs() << " S: " << Twine::utohexstr(S);
+ llvm::dbgs() << " A: " << Twine::utohexstr(A);
+ llvm::dbgs() << " P: " << Twine::utohexstr(P);
+ llvm::dbgs() << " result: " << Twine::utohexstr(result)
+ << "\n");
+ *reinterpret_cast<llvm::support::little32_t *>(location) =
+ result |
+ (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+/// \brief R_AARCH64_TLSLE_ADD_TPREL_LO12_NC
+static void relocR_AARCH64_TLSLE_ADD_TPREL_LO12_NC(uint8_t *location,
+ uint64_t P, uint64_t S,
+ int64_t A) {
+ int32_t result = S + A;
+ result &= 0x0FFF;
+ result <<= 10;
+ DEBUG_WITH_TYPE("AArch64", llvm::dbgs() << "\t\tHandle " << __func__ << " -";
+ llvm::dbgs() << " S: " << Twine::utohexstr(S);
+ llvm::dbgs() << " A: " << Twine::utohexstr(A);
+ llvm::dbgs() << " P: " << Twine::utohexstr(P);
+ llvm::dbgs() << " result: " << Twine::utohexstr(result)
+ << "\n");
+ *reinterpret_cast<llvm::support::little32_t *>(location) =
+ result |
+ (int32_t) * reinterpret_cast<llvm::support::little32_t *>(location);
+}
+
+int64_t
+AArch64TargetRelocationHandler::relocAddend(const Reference &ref) const {
+ if (ref.kindNamespace() != Reference::KindNamespace::ELF)
+ return false;
+ assert(ref.kindArch() == Reference::KindArch::AArch64);
+ switch (ref.kindValue()) {
+ case R_AARCH64_PREL32:
+ return 4;
+ default:
+ return 0;
+ }
+ return 0;
+}
+
+std::error_code AArch64TargetRelocationHandler::applyRelocation(
+ ELFWriter &writer, llvm::FileOutputBuffer &buf, const lld::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();
+
+ if (ref.kindNamespace() != Reference::KindNamespace::ELF)
+ return std::error_code();
+ assert(ref.kindArch() == Reference::KindArch::AArch64);
+ switch (ref.kindValue()) {
+ case R_AARCH64_NONE:
+ break;
+ case R_AARCH64_ABS64:
+ relocR_AARCH64_ABS64(location, relocVAddress, targetVAddress, ref.addend());
+ break;
+ case R_AARCH64_PREL32:
+ relocR_AARCH64_PREL32(location, relocVAddress, targetVAddress,
+ ref.addend());
+ break;
+ case R_AARCH64_ABS32:
+ relocR_AARCH64_ABS32(location, relocVAddress, targetVAddress, ref.addend());
+ break;
+ // Runtime only relocations. Ignore here.
+ case R_AARCH64_RELATIVE:
+ case R_AARCH64_IRELATIVE:
+ case R_AARCH64_JUMP_SLOT:
+ case R_AARCH64_GLOB_DAT:
+ break;
+ case R_AARCH64_ADR_PREL_PG_HI21:
+ relocR_AARCH64_ADR_PREL_PG_HI21(location, relocVAddress, targetVAddress,
+ ref.addend());
+ break;
+ case R_AARCH64_ADR_PREL_LO21:
+ relocR_AARCH64_ADR_PREL_LO21(location, relocVAddress, targetVAddress,
+ ref.addend());
+ break;
+ case R_AARCH64_ADD_ABS_LO12_NC:
+ relocR_AARCH64_ADD_ABS_LO12_NC(location, relocVAddress, targetVAddress,
+ ref.addend());
+ break;
+ case R_AARCH64_CALL26:
+ case R_AARCH64_JUMP26:
+ relocJump26(location, relocVAddress, targetVAddress, ref.addend());
+ break;
+ case R_AARCH64_CONDBR19:
+ relocR_AARCH64_CONDBR19(location, relocVAddress, targetVAddress,
+ ref.addend());
+ break;
+ case R_AARCH64_ADR_GOT_PAGE:
+ relocR_AARCH64_ADR_GOT_PAGE(location, relocVAddress, targetVAddress,
+ ref.addend());
+ break;
+ case R_AARCH64_LD64_GOT_LO12_NC:
+ relocR_AARCH64_LD64_GOT_LO12_NC(location, relocVAddress, targetVAddress,
+ ref.addend());
+ break;
+ case R_AARCH64_LDST8_ABS_LO12_NC:
+ relocR_AARCH64_LDST8_ABS_LO12_NC(location, relocVAddress, targetVAddress,
+ ref.addend());
+ break;
+ case R_AARCH64_LDST16_ABS_LO12_NC:
+ relocR_AARCH64_LDST16_ABS_LO12_NC(location, relocVAddress, targetVAddress,
+ ref.addend());
+ break;
+ case R_AARCH64_LDST32_ABS_LO12_NC:
+ relocR_AARCH64_LDST32_ABS_LO12_NC(location, relocVAddress, targetVAddress,
+ ref.addend());
+ break;
+ case R_AARCH64_LDST64_ABS_LO12_NC:
+ relocR_AARCH64_LDST64_ABS_LO12_NC(location, relocVAddress, targetVAddress,
+ ref.addend());
+ break;
+ case R_AARCH64_LDST128_ABS_LO12_NC:
+ relocR_AARCH64_LDST128_ABS_LO12_NC(location, relocVAddress, targetVAddress,
+ ref.addend());
+ break;
+ case ADD_AARCH64_GOTRELINDEX:
+ relocADD_AARCH64_GOTRELINDEX(location, relocVAddress, targetVAddress,
+ ref.addend());
+ break;
+ case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+ relocR_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21(location, relocVAddress,
+ targetVAddress, ref.addend());
+ break;
+ case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+ relocR_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC(location, relocVAddress,
+ targetVAddress, ref.addend());
+ break;
+ case R_AARCH64_TLSLE_ADD_TPREL_HI12:
+ relocR_AARCH64_TLSLE_ADD_TPREL_HI12(location, relocVAddress, targetVAddress,
+ ref.addend());
+ break;
+ case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+ relocR_AARCH64_TLSLE_ADD_TPREL_LO12_NC(location, relocVAddress,
+ targetVAddress, ref.addend());
+ break;
+ default: {
+ std::string str;
+ llvm::raw_string_ostream s(str);
+ s << "Unhandled relocation: " << atom._atom->file().path() << ":"
+ << atom._atom->name() << "@" << ref.offsetInAtom() << " "
+ << "#" << ref.kindValue();
+ s.flush();
+ llvm_unreachable(str.c_str());
+ }
+ }
+
+ return std::error_code();
+}
Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h Wed Aug 13 08:16:38 2014
@@ -0,0 +1,44 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h ------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef AARCH64_RELOCATION_HANDLER_H
+#define AARCH64_RELOCATION_HANDLER_H
+
+#include "AArch64TargetHandler.h"
+
+namespace lld {
+namespace elf {
+typedef llvm::object::ELFType<llvm::support::little, 2, true> AArch64ELFType;
+
+template <class ELFT> class AArch64TargetLayout;
+
+class AArch64TargetRelocationHandler final
+ : public TargetRelocationHandler<AArch64ELFType> {
+public:
+ AArch64TargetRelocationHandler(AArch64TargetLayout<AArch64ELFType> &layout)
+ : _tlsSize(0), _AArch64Layout(layout) {}
+
+ std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
+ const lld::AtomLayout &,
+ const Reference &) const override;
+
+ virtual int64_t relocAddend(const Reference &) const;
+
+ static const Registry::KindStrings kindStrings[];
+
+private:
+ // Cached size of the TLS segment.
+ mutable uint64_t _tlsSize;
+ AArch64TargetLayout<AArch64ELFType> &_AArch64Layout;
+};
+
+} // end namespace elf
+} // end namespace lld
+
+#endif // AArch64_RELOCATION_HANDLER_H
Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp Wed Aug 13 08:16:38 2014
@@ -0,0 +1,535 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp -------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the relocation processing pass for AArch64. This includes
+/// GOT and PLT entries, TLS, COPY, and ifunc.
+///
+/// This also includes additional behavior that gnu-ld and gold implement but
+/// which is not specified anywhere.
+///
+//===----------------------------------------------------------------------===//
+
+#include "AArch64RelocationPass.h"
+
+#include "lld/Core/Simple.h"
+
+#include "llvm/ADT/DenseMap.h"
+
+#include "Atoms.h"
+#include "AArch64LinkingContext.h"
+#include "llvm/Support/Debug.h"
+
+using namespace lld;
+using namespace lld::elf;
+using namespace llvm::ELF;
+
+namespace {
+// .got values
+const uint8_t AArch64GotAtomContent[8] = {0};
+
+// .plt value (entry 0)
+const uint8_t AArch64Plt0AtomContent[32] = {
+ 0xf0, 0x7b, 0xbf,
+ 0xa9, // stp x16, x30, [sp,#-16]!
+ 0x10, 0x00, 0x00,
+ 0x90, // adrp x16, Page(eh_frame)
+ 0x11, 0x02, 0x40,
+ 0xf9, // ldr x17, [x16,#offset]
+ 0x10, 0x02, 0x00,
+ 0x91, // add x16, x16, #offset
+ 0x20, 0x02, 0x1f,
+ 0xd6, // br x17
+ 0x1f, 0x20, 0x03,
+ 0xd5, // nop
+ 0x1f, 0x20, 0x03,
+ 0xd5, // nop
+ 0x1f, 0x20, 0x03,
+ 0xd5 // nop
+};
+
+// .plt values (other entries)
+const uint8_t AArch64PltAtomContent[16] = {
+ 0x10, 0x00, 0x00,
+ 0x90, // adrp x16, PAGE(<GLOBAL_OFFSET_TABLE>)
+ 0x11, 0x02, 0x40,
+ 0xf9, // ldr x17, [x16,#offset]
+ 0x10, 0x02, 0x00,
+ 0x91, // add x16, x16, #offset
+ 0x20, 0x02, 0x1f,
+ 0xd6 // br x17
+};
+
+/// \brief Atoms that are used by AArch64 dynamic linking
+class AArch64GOTAtom : public GOTAtom {
+public:
+ AArch64GOTAtom(const File &f, StringRef secName) : GOTAtom(f, secName) {}
+
+ ArrayRef<uint8_t> rawContent() const override {
+ return ArrayRef<uint8_t>(AArch64GotAtomContent, 8);
+ }
+};
+
+class AArch64PLT0Atom : public PLT0Atom {
+public:
+ AArch64PLT0Atom(const File &f) : PLT0Atom(f) {
+#ifndef NDEBUG
+ _name = ".PLT0";
+#endif
+ }
+ ArrayRef<uint8_t> rawContent() const override {
+ return ArrayRef<uint8_t>(AArch64Plt0AtomContent, 32);
+ }
+};
+
+class AArch64PLTAtom : public PLTAtom {
+public:
+ AArch64PLTAtom(const File &f, StringRef secName) : PLTAtom(f, secName) {}
+
+ ArrayRef<uint8_t> rawContent() const override {
+ return ArrayRef<uint8_t>(AArch64PltAtomContent, 16);
+ }
+};
+
+class ELFPassFile : public SimpleFile {
+public:
+ ELFPassFile(const ELFLinkingContext &eti) : SimpleFile("ELFPassFile") {
+ setOrdinal(eti.getNextOrdinalAndIncrement());
+ }
+
+ llvm::BumpPtrAllocator _alloc;
+};
+
+/// \brief CRTP base for handling relocations.
+template <class Derived> class AArch64RelocationPass : public Pass {
+ /// \brief Handle a specific reference.
+ void handleReference(const DefinedAtom &atom, const Reference &ref) {
+ DEBUG_WITH_TYPE(
+ "AArch64", llvm::dbgs()
+ << "\t" << __func__ << "()"
+ << ": Name of Defined Atom: " << atom.name().str();
+ llvm::dbgs() << " kindValue: " << ref.kindValue() << "\n");
+ if (ref.kindNamespace() != Reference::KindNamespace::ELF)
+ return;
+ assert(ref.kindArch() == Reference::KindArch::AArch64);
+ switch (ref.kindValue()) {
+ case R_AARCH64_ABS32:
+ case R_AARCH64_ABS16:
+ case R_AARCH64_ABS64:
+ case R_AARCH64_PREL16:
+ case R_AARCH64_PREL32:
+ case R_AARCH64_PREL64:
+ static_cast<Derived *>(this)->handlePlain(ref);
+ break;
+ case R_AARCH64_GOTREL32:
+ case R_AARCH64_GOTREL64:
+ static_cast<Derived *>(this)->handleGOT(ref);
+ break;
+ case R_AARCH64_ADR_PREL_PG_HI21:
+ static_cast<Derived *>(this)->handlePlain(ref);
+ break;
+ case R_AARCH64_LDST8_ABS_LO12_NC:
+ case R_AARCH64_LDST16_ABS_LO12_NC:
+ case R_AARCH64_LDST32_ABS_LO12_NC:
+ case R_AARCH64_LDST64_ABS_LO12_NC:
+ case R_AARCH64_LDST128_ABS_LO12_NC:
+ static_cast<Derived *>(this)->handlePlain(ref);
+ break;
+ case R_AARCH64_ADD_ABS_LO12_NC:
+ static_cast<Derived *>(this)->handlePlain(ref);
+ break;
+ case R_AARCH64_CALL26:
+ case R_AARCH64_JUMP26:
+ case R_AARCH64_CONDBR19:
+ static_cast<Derived *>(this)->handlePlain(ref);
+ break;
+ case R_AARCH64_TLSLE_ADD_TPREL_HI12:
+ case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+ static_cast<Derived *>(this)->handlePlain(ref);
+ break;
+ case R_AARCH64_ADR_GOT_PAGE:
+ case R_AARCH64_LD64_GOT_LO12_NC:
+ case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+ case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+ static_cast<Derived *>(this)->handleGOT(ref);
+ break;
+ default:
+ llvm_unreachable("Unhandled type in handleReference");
+ }
+ }
+
+protected:
+ /// \brief get the PLT entry for a given IFUNC Atom.
+ ///
+ /// If the entry does not exist. Both the GOT and PLT entry is created.
+ const PLTAtom *getIFUNCPLTEntry(const DefinedAtom *da) {
+ auto plt = _pltMap.find(da);
+ if (plt != _pltMap.end())
+ return plt->second;
+ auto ga = new (_file._alloc) AArch64GOTAtom(_file, ".got.plt");
+ ga->addReferenceELF_AArch64(R_AARCH64_IRELATIVE, 0, da, 0);
+ auto pa = new (_file._alloc) AArch64PLTAtom(_file, ".plt");
+ pa->addReferenceELF_AArch64(R_AARCH64_PREL32, 2, ga, -4);
+#ifndef NDEBUG
+ ga->_name = "__got_ifunc_";
+ ga->_name += da->name();
+ pa->_name = "__plt_ifunc_";
+ pa->_name += da->name();
+#endif
+ _gotMap[da] = ga;
+ _pltMap[da] = pa;
+ _gotVector.push_back(ga);
+ _pltVector.push_back(pa);
+ return pa;
+ }
+
+ /// \brief Redirect the call to the PLT stub for the target IFUNC.
+ ///
+ /// This create a PLT and GOT entry for the IFUNC if one does not exist. The
+ /// GOT entry and a IRELATIVE relocation to the original target resolver.
+ std::error_code handleIFUNC(const Reference &ref) {
+ auto target = dyn_cast_or_null<const DefinedAtom>(ref.target());
+ if (target && target->contentType() == DefinedAtom::typeResolver)
+ const_cast<Reference &>(ref).setTarget(getIFUNCPLTEntry(target));
+ return std::error_code();
+ }
+
+ /// \brief Create a GOT entry for the TP offset of a TLS atom.
+ const GOTAtom *getGOTTPOFF(const Atom *atom) {
+ auto got = _gotMap.find(atom);
+ if (got == _gotMap.end()) {
+ auto g = new (_file._alloc) AArch64GOTAtom(_file, ".got");
+ g->addReferenceELF_AArch64(R_AARCH64_GOTREL64, 0, atom, 0);
+#ifndef NDEBUG
+ g->_name = "__got_tls_";
+ g->_name += atom->name();
+#endif
+ _gotMap[atom] = g;
+ _gotVector.push_back(g);
+ return g;
+ }
+ 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_AARCH64_PREL32);
+ }
+
+ /// \brief Create a GOT entry containing 0.
+ const GOTAtom *getNullGOT() {
+ if (!_null) {
+ _null = new (_file._alloc) AArch64GOTAtom(_file, ".got.plt");
+#ifndef NDEBUG
+ _null->_name = "__got_null";
+#endif
+ }
+ return _null;
+ }
+
+ const GOTAtom *getGOT(const DefinedAtom *da) {
+ auto got = _gotMap.find(da);
+ if (got == _gotMap.end()) {
+ auto g = new (_file._alloc) AArch64GOTAtom(_file, ".got");
+ g->addReferenceELF_AArch64(R_AARCH64_ABS64, 0, da, 0);
+#ifndef NDEBUG
+ g->_name = "__got_";
+ g->_name += da->name();
+#endif
+ _gotMap[da] = g;
+ _gotVector.push_back(g);
+ return g;
+ }
+ return got->second;
+ }
+
+public:
+ AArch64RelocationPass(const ELFLinkingContext &ctx)
+ : _file(ctx), _ctx(ctx), _null(nullptr), _PLT0(nullptr), _got0(nullptr),
+ _got1(nullptr) {}
+
+ /// \brief Do the pass.
+ ///
+ /// The goal here is to first process each reference individually. Each call
+ /// to handleReference may modify the reference itself and/or create new
+ /// atoms which must be stored in one of the maps below.
+ ///
+ /// After all references are handled, the atoms created during that are all
+ /// added to mf.
+ void perform(std::unique_ptr<MutableFile> &mf) override {
+ ScopedTask task(getDefaultDomain(), "AArch64 GOT/PLT Pass");
+ DEBUG_WITH_TYPE(
+ "AArch64", llvm::dbgs() << "Undefined Atoms"
+ << "\n";
+ for (const auto &atom
+ : mf->undefined()) {
+ llvm::dbgs() << " Name of Atom: " << atom->name().str() << "\n";
+ } llvm::dbgs()
+ << "Shared Library Atoms"
+ << "\n";
+ for (const auto &atom
+ : mf->sharedLibrary()) {
+ llvm::dbgs() << " Name of Atom: " << atom->name().str() << "\n";
+ } llvm::dbgs()
+ << "Absolute Atoms"
+ << "\n";
+ for (const auto &atom
+ : mf->absolute()) {
+ llvm::dbgs() << " Name of Atom: " << atom->name().str() << "\n";
+ }
+ // Process all references.
+ llvm::dbgs()
+ << "Defined Atoms"
+ << "\n");
+ 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);
+ }
+ for (auto &plt : _pltVector) {
+ plt->setOrdinal(ordinal++);
+ mf->addAtom(*plt);
+ }
+ if (_null) {
+ _null->setOrdinal(ordinal++);
+ mf->addAtom(*_null);
+ }
+ if (_PLT0) {
+ _got0->setOrdinal(ordinal++);
+ _got1->setOrdinal(ordinal++);
+ mf->addAtom(*_got0);
+ mf->addAtom(*_got1);
+ }
+ for (auto &got : _gotVector) {
+ got->setOrdinal(ordinal++);
+ mf->addAtom(*got);
+ }
+ for (auto obj : _objectVector) {
+ obj->setOrdinal(ordinal++);
+ mf->addAtom(*obj);
+ }
+ }
+
+protected:
+ /// \brief Owner of all the Atoms created by this pass.
+ ELFPassFile _file;
+ const ELFLinkingContext &_ctx;
+
+ /// \brief Map Atoms to their GOT entries.
+ llvm::DenseMap<const Atom *, GOTAtom *> _gotMap;
+
+ /// \brief Map Atoms to their PLT entries.
+ llvm::DenseMap<const Atom *, PLTAtom *> _pltMap;
+
+ /// \brief Map Atoms to their Object entries.
+ llvm::DenseMap<const Atom *, ObjectAtom *> _objectMap;
+
+ /// \brief the list of GOT/PLT atoms
+ std::vector<GOTAtom *> _gotVector;
+ std::vector<PLTAtom *> _pltVector;
+ std::vector<ObjectAtom *> _objectVector;
+
+ /// \brief GOT entry that is always 0. Used for undefined weaks.
+ GOTAtom *_null;
+
+ /// \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;
+ /// @}
+};
+
+/// This implements the static relocation model. Meaning GOT and PLT entries are
+/// not created for references that can be directly resolved. These are
+/// converted to a direct relocation. For entries that do require a GOT or PLT
+/// entry, that entry is statically bound.
+///
+/// TLS always assumes module 1 and attempts to remove indirection.
+class AArch64StaticRelocationPass final
+ : public AArch64RelocationPass<AArch64StaticRelocationPass> {
+public:
+ AArch64StaticRelocationPass(const elf::AArch64LinkingContext &ctx)
+ : AArch64RelocationPass(ctx) {}
+
+ std::error_code handlePlain(const Reference &ref) { return handleIFUNC(ref); }
+
+ std::error_code handlePLT32(const Reference &ref) {
+ // __tls_get_addr is handled elsewhere.
+ if (ref.target() && ref.target()->name() == "__tls_get_addr") {
+ const_cast<Reference &>(ref).setKindValue(R_AARCH64_NONE);
+ return std::error_code();
+ }
+ // Static code doesn't need PLTs.
+ const_cast<Reference &>(ref).setKindValue(R_AARCH64_PREL32);
+ // Handle IFUNC.
+ if (const DefinedAtom *da =
+ dyn_cast_or_null<const DefinedAtom>(ref.target()))
+ if (da->contentType() == DefinedAtom::typeResolver)
+ return handleIFUNC(ref);
+ return std::error_code();
+ }
+
+ std::error_code handleGOT(const Reference &ref) {
+ if (isa<UndefinedAtom>(ref.target()))
+ const_cast<Reference &>(ref).setTarget(getNullGOT());
+ else if (const DefinedAtom *da = dyn_cast<const DefinedAtom>(ref.target()))
+ const_cast<Reference &>(ref).setTarget(getGOT(da));
+ return std::error_code();
+ }
+};
+
+class AArch64DynamicRelocationPass final
+ : public AArch64RelocationPass<AArch64DynamicRelocationPass> {
+public:
+ AArch64DynamicRelocationPass(const elf::AArch64LinkingContext &ctx)
+ : AArch64RelocationPass(ctx) {}
+
+ const PLT0Atom *getPLT0() {
+ if (_PLT0)
+ return _PLT0;
+ // Fill in the null entry.
+ getNullGOT();
+ _PLT0 = new (_file._alloc) AArch64PLT0Atom(_file);
+ _got0 = new (_file._alloc) AArch64GOTAtom(_file, ".got.plt");
+ _got1 = new (_file._alloc) AArch64GOTAtom(_file, ".got.plt");
+ _PLT0->addReferenceELF_AArch64(R_AARCH64_ADR_GOT_PAGE, 4, _got0, 0);
+ _PLT0->addReferenceELF_AArch64(R_AARCH64_LD64_GOT_LO12_NC, 8, _got1, 0);
+ _PLT0->addReferenceELF_AArch64(ADD_AARCH64_GOTRELINDEX, 12, _got1, 0);
+#ifndef NDEBUG
+ _got0->_name = "__got0";
+ _got1->_name = "__got1";
+#endif
+ return _PLT0;
+ }
+
+ const PLTAtom *getPLTEntry(const Atom *a) {
+ auto plt = _pltMap.find(a);
+ if (plt != _pltMap.end())
+ return plt->second;
+ auto ga = new (_file._alloc) AArch64GOTAtom(_file, ".got.plt");
+ ga->addReferenceELF_AArch64(R_AARCH64_JUMP_SLOT, 0, a, 0);
+ auto pa = new (_file._alloc) AArch64PLTAtom(_file, ".plt");
+ pa->addReferenceELF_AArch64(R_AARCH64_ADR_GOT_PAGE, 0, ga, 0);
+ pa->addReferenceELF_AArch64(R_AARCH64_LD64_GOT_LO12_NC, 4, ga, 0);
+ pa->addReferenceELF_AArch64(ADD_AARCH64_GOTRELINDEX, 8, ga, 0);
+ pa->addReferenceELF_AArch64(R_AARCH64_NONE, 12, getPLT0(), 0);
+ // Set the starting address of the got entry to the first instruction in
+ // the plt0 entry.
+ ga->addReferenceELF_AArch64(R_AARCH64_ABS32, 0, pa, 0);
+#ifndef NDEBUG
+ ga->_name = "__got_";
+ ga->_name += a->name();
+ pa->_name = "__plt_";
+ pa->_name += a->name();
+#endif
+ _gotMap[a] = ga;
+ _pltMap[a] = pa;
+ _gotVector.push_back(ga);
+ _pltVector.push_back(pa);
+ return pa;
+ }
+
+ const ObjectAtom *getObjectEntry(const SharedLibraryAtom *a) {
+ auto obj = _objectMap.find(a);
+ if (obj != _objectMap.end())
+ return obj->second;
+
+ auto oa = new (_file._alloc) ObjectAtom(_file);
+ // This needs to point to the atom that we just created.
+ oa->addReferenceELF_AArch64(R_AARCH64_COPY, 0, oa, 0);
+
+ oa->_name = a->name();
+ oa->_size = a->size();
+
+ _objectMap[a] = oa;
+ _objectVector.push_back(oa);
+ return oa;
+ }
+
+ std::error_code handlePlain(const Reference &ref) {
+ if (!ref.target())
+ return std::error_code();
+ if (auto sla = dyn_cast<SharedLibraryAtom>(ref.target())) {
+ if (sla->type() == SharedLibraryAtom::Type::Data)
+ const_cast<Reference &>(ref).setTarget(getObjectEntry(sla));
+ else if (sla->type() == SharedLibraryAtom::Type::Code)
+ const_cast<Reference &>(ref).setTarget(getPLTEntry(sla));
+ } else
+ return handleIFUNC(ref);
+ return std::error_code();
+ }
+
+ std::error_code handlePLT32(const Reference &ref) {
+ // Turn this into a PC32 to the PLT entry.
+ const_cast<Reference &>(ref).setKindValue(R_AARCH64_PREL32);
+ // Handle IFUNC.
+ if (const DefinedAtom *da =
+ dyn_cast_or_null<const DefinedAtom>(ref.target()))
+ if (da->contentType() == DefinedAtom::typeResolver)
+ return handleIFUNC(ref);
+ if (isa<const SharedLibraryAtom>(ref.target()))
+ const_cast<Reference &>(ref).setTarget(getPLTEntry(ref.target()));
+ return std::error_code();
+ }
+
+ const GOTAtom *getSharedGOT(const SharedLibraryAtom *sla) {
+ auto got = _gotMap.find(sla);
+ if (got == _gotMap.end()) {
+ auto g = new (_file._alloc) AArch64GOTAtom(_file, ".got.dyn");
+ g->addReferenceELF_AArch64(R_AARCH64_GLOB_DAT, 0, sla, 0);
+#ifndef NDEBUG
+ g->_name = "__got_";
+ g->_name += sla->name();
+#endif
+ _gotMap[sla] = g;
+ _gotVector.push_back(g);
+ return g;
+ }
+ return got->second;
+ }
+
+ std::error_code handleGOT(const Reference &ref) {
+ if (isa<UndefinedAtom>(ref.target()))
+ const_cast<Reference &>(ref).setTarget(getNullGOT());
+ else if (const DefinedAtom *da = dyn_cast<const DefinedAtom>(ref.target()))
+ const_cast<Reference &>(ref).setTarget(getGOT(da));
+ else if (const auto sla = dyn_cast<const SharedLibraryAtom>(ref.target()))
+ const_cast<Reference &>(ref).setTarget(getSharedGOT(sla));
+ return std::error_code();
+ }
+};
+} // end anon namespace
+
+std::unique_ptr<Pass>
+lld::elf::createAArch64RelocationPass(const AArch64LinkingContext &ctx) {
+ switch (ctx.getOutputELFType()) {
+ case llvm::ELF::ET_EXEC:
+ if (ctx.isDynamic())
+ return std::unique_ptr<Pass>(new AArch64DynamicRelocationPass(ctx));
+ else
+ return std::unique_ptr<Pass>(new AArch64StaticRelocationPass(ctx));
+ case llvm::ELF::ET_DYN:
+ return std::unique_ptr<Pass>(new AArch64DynamicRelocationPass(ctx));
+ case llvm::ELF::ET_REL:
+ return std::unique_ptr<Pass>();
+ default:
+ llvm_unreachable("Unhandled output file type");
+ }
+}
Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.h?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.h Wed Aug 13 08:16:38 2014
@@ -0,0 +1,32 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.h ---------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Declares the relocation processing pass for x86-64. This includes
+/// GOT and PLT entries, TLS, COPY, and ifunc.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_ELF_AARCH64_AARCH64_RELOCATION_PASS_H
+#define LLD_READER_WRITER_ELF_AARCH64_AARCH64_RELOCATION_PASS_H
+
+#include <memory>
+
+namespace lld {
+class Pass;
+namespace elf {
+class AArch64LinkingContext;
+
+/// \brief Create AArch64 relocation pass for the given linking context.
+std::unique_ptr<Pass>
+createAArch64RelocationPass(const AArch64LinkingContext &);
+}
+}
+
+#endif
Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64Target.h?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64Target.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64Target.h Wed Aug 13 08:16:38 2014
@@ -0,0 +1,10 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64Target.h -----------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AArch64LinkingContext.h"
Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp Wed Aug 13 08:16:38 2014
@@ -0,0 +1,129 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp --------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Atoms.h"
+#include "AArch64ExecutableWriter.h"
+#include "AArch64DynamicLibraryWriter.h"
+#include "AArch64TargetHandler.h"
+#include "AArch64LinkingContext.h"
+
+using namespace lld;
+using namespace elf;
+
+AArch64TargetHandler::AArch64TargetHandler(AArch64LinkingContext &context)
+ : DefaultTargetHandler(context), _context(context),
+ _AArch64TargetLayout(new AArch64TargetLayout<AArch64ELFType>(context)),
+ _AArch64RelocationHandler(
+ new AArch64TargetRelocationHandler(*_AArch64TargetLayout.get())) {}
+
+void AArch64TargetHandler::registerRelocationNames(Registry ®istry) {
+ registry.addKindTable(Reference::KindNamespace::ELF,
+ Reference::KindArch::AArch64, kindStrings);
+}
+
+std::unique_ptr<Writer> AArch64TargetHandler::getWriter() {
+ switch (this->_context.getOutputELFType()) {
+ case llvm::ELF::ET_EXEC:
+ return std::unique_ptr<Writer>(new AArch64ExecutableWriter<AArch64ELFType>(
+ _context, *_AArch64TargetLayout.get()));
+ case llvm::ELF::ET_DYN:
+ return std::unique_ptr<Writer>(
+ new AArch64DynamicLibraryWriter<AArch64ELFType>(
+ _context, *_AArch64TargetLayout.get()));
+ case llvm::ELF::ET_REL:
+ llvm_unreachable("TODO: support -r mode");
+ default:
+ llvm_unreachable("unsupported output type");
+ }
+}
+
+const Registry::KindStrings AArch64TargetHandler::kindStrings[] = {
+ LLD_KIND_STRING_ENTRY(R_AARCH64_NONE),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_ABS64),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_ABS32),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_ABS16),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_PREL64),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_PREL32),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_PREL16),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_MOVW_UABS_G0),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_MOVW_UABS_G0_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_MOVW_UABS_G1),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_MOVW_UABS_G1_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_MOVW_UABS_G2),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_MOVW_UABS_G2_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_MOVW_UABS_G3),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_MOVW_SABS_G0),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_MOVW_SABS_G1),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_MOVW_SABS_G2),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_LD_PREL_LO19),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_ADR_PREL_LO21),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_ADR_PREL_PG_HI21),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_ADD_ABS_LO12_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_LDST8_ABS_LO12_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TSTBR14),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_CONDBR19),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_JUMP26),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_CALL26),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_LDST16_ABS_LO12_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_LDST32_ABS_LO12_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_LDST64_ABS_LO12_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_LDST128_ABS_LO12_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_ADR_GOT_PAGE),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_LD64_GOT_LO12_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_MOVW_DTPREL_G2),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_MOVW_DTPREL_G1),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_MOVW_DTPREL_G0),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_ADD_DTPREL_HI12),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_ADD_DTPREL_LO12),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_LDST8_DTPREL_LO12),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_LDST16_DTPREL_LO12),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_LDST32_DTPREL_LO12),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_LDST64_DTPREL_LO12),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSIE_MOVW_GOTTPREL_G1),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSIE_LD_GOTTPREL_PREL19),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_MOVW_TPREL_G2),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_MOVW_TPREL_G1),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_MOVW_TPREL_G1_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_MOVW_TPREL_G0),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_MOVW_TPREL_G0_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_ADD_TPREL_HI12),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_ADD_TPREL_LO12),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_ADD_TPREL_LO12_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_LDST8_TPREL_LO12),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_LDST16_TPREL_LO12),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_LDST32_TPREL_LO12),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_LDST64_TPREL_LO12),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSDESC_ADR_PAGE),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSDESC_LD64_LO12_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSDESC_ADD_LO12_NC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSDESC_CALL),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_COPY),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_GLOB_DAT),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_JUMP_SLOT),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_RELATIVE),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLS_DTPREL64),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLS_DTPMOD64),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLS_TPREL64),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_TLSDESC),
+ LLD_KIND_STRING_ENTRY(R_AARCH64_IRELATIVE),
+ LLD_KIND_STRING_END};
Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h Wed Aug 13 08:16:38 2014
@@ -0,0 +1,57 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.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_AARCH64_AARCH64_TARGET_HANDLER_H
+#define LLD_READER_WRITER_ELF_AARCH64_AARCH64_TARGET_HANDLER_H
+
+#include "DefaultTargetHandler.h"
+#include "ELFFile.h"
+#include "AArch64RelocationHandler.h"
+#include "TargetLayout.h"
+
+#include "lld/Core/Simple.h"
+
+namespace lld {
+namespace elf {
+typedef llvm::object::ELFType<llvm::support::little, 2, true> AArch64ELFType;
+class AArch64LinkingContext;
+
+template <class ELFT> class AArch64TargetLayout : public TargetLayout<ELFT> {
+public:
+ AArch64TargetLayout(AArch64LinkingContext &context)
+ : TargetLayout<ELFT>(context) {}
+};
+
+class AArch64TargetHandler final : public DefaultTargetHandler<AArch64ELFType> {
+public:
+ AArch64TargetHandler(AArch64LinkingContext &context);
+
+ AArch64TargetLayout<AArch64ELFType> &getTargetLayout() override {
+ return *(_AArch64TargetLayout.get());
+ }
+
+ void registerRelocationNames(Registry ®istry) override;
+
+ const AArch64TargetRelocationHandler &getRelocationHandler() const override {
+ return *(_AArch64RelocationHandler.get());
+ }
+
+ std::unique_ptr<Writer> getWriter() override;
+
+private:
+ static const Registry::KindStrings kindStrings[];
+ AArch64LinkingContext &_context;
+ std::unique_ptr<AArch64TargetLayout<AArch64ELFType>> _AArch64TargetLayout;
+ std::unique_ptr<AArch64TargetRelocationHandler> _AArch64RelocationHandler;
+};
+
+} // end namespace elf
+} // end namespace lld
+
+#endif
Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt Wed Aug 13 08:16:38 2014
@@ -0,0 +1,10 @@
+add_lld_library(lldAArch64ELFTarget
+ AArch64LinkingContext.cpp
+ AArch64TargetHandler.cpp
+ AArch64RelocationHandler.cpp
+ AArch64RelocationPass.cpp
+ )
+
+target_link_libraries(lldAArch64ELFTarget
+ lldCore
+ )
Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/Makefile
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/Makefile?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/Makefile (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/Makefile Wed Aug 13 08:16:38 2014
@@ -0,0 +1,15 @@
+##===- lld/lib/ReaderWriter/ELF/AArch64/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 := lldAArch64ELFTarget
+USEDLIBS = lldCore.a
+CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLD_LEVEL)/lib/ReaderWriter/ELF/AArch64 -I$(PROJ_SRC_DIR)/$(LLD_LEVEL)/lib/ReaderWriter/ELF
+
+include $(LLD_LEVEL)/Makefile
Added: lld/trunk/lib/ReaderWriter/ELF/AArch64/TODO.rst
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/TODO.rst?rev=215544&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/AArch64/TODO.rst (added)
+++ lld/trunk/lib/ReaderWriter/ELF/AArch64/TODO.rst Wed Aug 13 08:16:38 2014
@@ -0,0 +1,15 @@
+ELF AArch64
+~~~~~~~~~~
+
+Unimplemented Features
+######################
+
+* Just about everything!
+
+Unimplemented Relocations
+#########################
+
+All of these relocations are defined in:
+http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf
+
+
Modified: lld/trunk/lib/ReaderWriter/ELF/Atoms.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Atoms.h?rev=215544&r1=215543&r2=215544&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Atoms.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Atoms.h Wed Aug 13 08:16:38 2014
@@ -679,6 +679,11 @@ public:
Reference::Addend a) {
this->addReferenceELF(Reference::KindArch::Mips, relocType, off, t, a);
}
+
+ void addReferenceELF_AArch64(uint16_t relocType, uint64_t off, const Atom *t,
+ Reference::Addend a) {
+ this->addReferenceELF(Reference::KindArch::AArch64, relocType, off, t, a);
+ }
};
/// \brief Atom which represents an object for which a COPY relocation will be
Modified: lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt?rev=215544&r1=215543&r2=215544&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt (original)
+++ lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt Wed Aug 13 08:16:38 2014
@@ -13,6 +13,7 @@ target_link_libraries(lldELF
lldReaderWriter
lldX86ELFTarget
lldX86_64ELFTarget
+ lldAArch64ELFTarget
)
include_directories(.)
Modified: lld/trunk/lib/ReaderWriter/ELF/ELFFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFFile.h?rev=215544&r1=215543&r2=215544&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ELFFile.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ELFFile.h Wed Aug 13 08:16:38 2014
@@ -452,6 +452,8 @@ template <class ELFT> Reference::KindArc
return Reference::KindArch::Hexagon;
case llvm::ELF::EM_MIPS:
return Reference::KindArch::Mips;
+ case llvm::ELF::EM_AARCH64:
+ return Reference::KindArch::AArch64;
}
llvm_unreachable("unsupported e_machine value");
}
Modified: lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp?rev=215544&r1=215543&r2=215544&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp Wed Aug 13 08:16:38 2014
@@ -87,6 +87,8 @@ uint16_t ELFLinkingContext::getOutputMac
return llvm::ELF::EM_MIPS;
case llvm::Triple::ppc:
return llvm::ELF::EM_PPC;
+ case llvm::Triple::aarch64:
+ return llvm::ELF::EM_AARCH64;
default:
llvm_unreachable("Unhandled arch");
}
@@ -147,6 +149,9 @@ ELFLinkingContext::create(llvm::Triple t
case llvm::Triple::ppc:
return std::unique_ptr<ELFLinkingContext>(
new lld::elf::PPCLinkingContext(triple));
+ case llvm::Triple::aarch64:
+ return std::unique_ptr<ELFLinkingContext>(
+ new lld::elf::AArch64LinkingContext(triple));
default:
return nullptr;
}
Modified: lld/trunk/lib/ReaderWriter/ELF/Makefile
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Makefile?rev=215544&r1=215543&r2=215544&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Makefile (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Makefile Wed Aug 13 08:16:38 2014
@@ -10,12 +10,12 @@
LLD_LEVEL := ../../..
LIBRARYNAME := lldELF
USEDLIBS = lldHexagonELFTarget.a lldPPCELFTarget.a lldMipsELFTarget.a \
- lldX86ELFTarget.a lldX86_64ELFTarget.a \
+ lldX86ELFTarget.a lldX86_64ELFTarget.a lldAArch64ELFTarget.a \
lldReaderWriter.a lldPasses.a
CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLD_LEVEL)/lib/ReaderWriter/ELF
# these link against this lib
-PARALLEL_DIRS := Hexagon PPC X86 X86_64 Mips
+PARALLEL_DIRS := Hexagon PPC X86 X86_64 Mips AArch64
include $(LLD_LEVEL)/Makefile
Modified: lld/trunk/lib/ReaderWriter/ELF/Targets.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Targets.h?rev=215544&r1=215543&r2=215544&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Targets.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Targets.h Wed Aug 13 08:16:38 2014
@@ -15,5 +15,6 @@
#include "PPC/PPCTarget.h"
#include "X86/X86Target.h"
#include "X86_64/X86_64Target.h"
+#include "AArch64/AArch64Target.h"
#endif
Added: lld/trunk/test/elf/AArch64/Inputs/fn.c
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/fn.c?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/Inputs/fn.c (added)
+++ lld/trunk/test/elf/AArch64/Inputs/fn.c Wed Aug 13 08:16:38 2014
@@ -0,0 +1,4 @@
+int fn()
+{
+ return 0;
+}
Added: lld/trunk/test/elf/AArch64/Inputs/fn.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/fn.o?rev=215544&view=auto
==============================================================================
Binary files lld/trunk/test/elf/AArch64/Inputs/fn.o (added) and lld/trunk/test/elf/AArch64/Inputs/fn.o Wed Aug 13 08:16:38 2014 differ
Added: lld/trunk/test/elf/AArch64/Inputs/initfini-option.c
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/initfini-option.c?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/Inputs/initfini-option.c (added)
+++ lld/trunk/test/elf/AArch64/Inputs/initfini-option.c Wed Aug 13 08:16:38 2014
@@ -0,0 +1,12 @@
+#include <stdio.h>
+
+void init() {
+ printf("%s\n", __FUNCTION__);
+}
+
+void fini() {
+ printf("%s\n", __FUNCTION__);
+}
+
+int main() {
+}
Added: lld/trunk/test/elf/AArch64/Inputs/initfini-option.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/initfini-option.o?rev=215544&view=auto
==============================================================================
Binary files lld/trunk/test/elf/AArch64/Inputs/initfini-option.o (added) and lld/trunk/test/elf/AArch64/Inputs/initfini-option.o Wed Aug 13 08:16:38 2014 differ
Added: lld/trunk/test/elf/AArch64/Inputs/initfini.c
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/initfini.c?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/Inputs/initfini.c (added)
+++ lld/trunk/test/elf/AArch64/Inputs/initfini.c Wed Aug 13 08:16:38 2014
@@ -0,0 +1,13 @@
+#include <stdio.h>
+
+void __attribute__ ((constructor)) constructor() {
+ printf("%s\n", __FUNCTION__);
+}
+
+void __attribute__ ((destructor)) destructor() {
+ printf("%s\n", __FUNCTION__);
+}
+
+int main() {
+ return 0;
+}
Added: lld/trunk/test/elf/AArch64/Inputs/initfini.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/initfini.o?rev=215544&view=auto
==============================================================================
Binary files lld/trunk/test/elf/AArch64/Inputs/initfini.o (added) and lld/trunk/test/elf/AArch64/Inputs/initfini.o Wed Aug 13 08:16:38 2014 differ
Added: lld/trunk/test/elf/AArch64/Inputs/main.c
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/main.c?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/Inputs/main.c (added)
+++ lld/trunk/test/elf/AArch64/Inputs/main.c Wed Aug 13 08:16:38 2014
@@ -0,0 +1,4 @@
+int main() {
+ fn();
+ return 0;
+}
Added: lld/trunk/test/elf/AArch64/Inputs/main.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/main.o?rev=215544&view=auto
==============================================================================
Binary files lld/trunk/test/elf/AArch64/Inputs/main.o (added) and lld/trunk/test/elf/AArch64/Inputs/main.o Wed Aug 13 08:16:38 2014 differ
Added: lld/trunk/test/elf/AArch64/Inputs/no-interp-section.c
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/no-interp-section.c?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/Inputs/no-interp-section.c (added)
+++ lld/trunk/test/elf/AArch64/Inputs/no-interp-section.c Wed Aug 13 08:16:38 2014
@@ -0,0 +1 @@
+int c = 10;
Added: lld/trunk/test/elf/AArch64/Inputs/no-interp-section.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/no-interp-section.o?rev=215544&view=auto
==============================================================================
Binary files lld/trunk/test/elf/AArch64/Inputs/no-interp-section.o (added) and lld/trunk/test/elf/AArch64/Inputs/no-interp-section.o Wed Aug 13 08:16:38 2014 differ
Added: lld/trunk/test/elf/AArch64/Inputs/zerosizedsection.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/zerosizedsection.o?rev=215544&view=auto
==============================================================================
Binary files lld/trunk/test/elf/AArch64/Inputs/zerosizedsection.o (added) and lld/trunk/test/elf/AArch64/Inputs/zerosizedsection.o Wed Aug 13 08:16:38 2014 differ
Added: lld/trunk/test/elf/AArch64/Inputs/zerosizedsection.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/Inputs/zerosizedsection.s?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/Inputs/zerosizedsection.s (added)
+++ lld/trunk/test/elf/AArch64/Inputs/zerosizedsection.s Wed Aug 13 08:16:38 2014
@@ -0,0 +1,3 @@
+.text
+.data
+.word .text
Added: lld/trunk/test/elf/AArch64/defsym.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/defsym.test?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/defsym.test (added)
+++ lld/trunk/test/elf/AArch64/defsym.test Wed Aug 13 08:16:38 2014
@@ -0,0 +1,22 @@
+RUN: lld -flavor gnu -target aarch64--linux-gnu --defsym=main=fn \
+RUN: --noinhibit-exec %p/Inputs/fn.o -o %t
+RUN: llvm-readobj -symbols %t | FileCheck %s
+
+CHECK: Symbol {
+CHECK: Name: main (1)
+CHECK: Value: 0x4001A4
+CHECK: Size: 0
+CHECK: Binding: Global (0x1)
+CHECK: Type: Function (0x2)
+CHECK: Other: 0
+CHECK: Section: .text (0x5)
+CHECK: }
+CHECK: Symbol {
+CHECK: Name: fn (6)
+CHECK: Value: 0x4001A4
+CHECK: Size: 8
+CHECK: Binding: Global (0x1)
+CHECK: Type: Function (0x2)
+CHECK: Other: 0
+CHECK: Section: .text (0x5)
+CHECK: }
Added: lld/trunk/test/elf/AArch64/dontignorezerosize-sections.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/dontignorezerosize-sections.test?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/dontignorezerosize-sections.test (added)
+++ lld/trunk/test/elf/AArch64/dontignorezerosize-sections.test Wed Aug 13 08:16:38 2014
@@ -0,0 +1,9 @@
+# This tests that lld is not ignoring zero sized sections
+RUN: lld -flavor gnu -target aarch64--linux-gnu %p/Inputs/zerosizedsection.o \
+RUN: --noinhibit-exec --output-filetype=yaml -o %t
+RUN: FileCheck %s < %t
+
+CHECK: references:
+CHECK: - kind: layout-after
+CHECK: offset: 0
+CHECK: target: L000
Added: lld/trunk/test/elf/AArch64/dynlib-nointerp-section.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/dynlib-nointerp-section.test?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/dynlib-nointerp-section.test (added)
+++ lld/trunk/test/elf/AArch64/dynlib-nointerp-section.test Wed Aug 13 08:16:38 2014
@@ -0,0 +1,5 @@
+RUN: lld -flavor gnu -target aarch64--linux-gnu %p/Inputs/no-interp-section.o \
+RUN: -o %t -shared
+RUN: llvm-objdump -section-headers %t | FileCheck %s
+
+CHECK-NOT: .interp
Added: lld/trunk/test/elf/AArch64/initfini-alignment.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/initfini-alignment.test?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/initfini-alignment.test (added)
+++ lld/trunk/test/elf/AArch64/initfini-alignment.test Wed Aug 13 08:16:38 2014
@@ -0,0 +1,12 @@
+# This tests the functionality that lld is able to create
+# init_array/fini_array sections in the output ELF with the
+# right alignment
+
+RUN: lld -flavor gnu -target aarch64--linux-gnu %p/Inputs/initfini-option.o \
+RUN: -init init -fini fini --noinhibit-exec -o %t
+RUN: llvm-readobj -s %t | FileCheck %s
+
+CHECK: Name: .init_array
+CHECK: AddressAlignment: 8
+CHECK: Name: .fini_array
+CHECK: AddressAlignment: 8
Added: lld/trunk/test/elf/AArch64/initfini-option.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/initfini-option.test?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/initfini-option.test (added)
+++ lld/trunk/test/elf/AArch64/initfini-option.test Wed Aug 13 08:16:38 2014
@@ -0,0 +1,21 @@
+# This tests the functionality that lld is able to create
+# init_array/fini_array sections in the output ELF. This
+# corresponds to the the .init_array/.fini_array sections
+# in the output ELF.
+
+RUN: lld -flavor gnu -target aarch64--linux-gnu %p/Inputs/initfini-option.o \
+RUN: -init init -fini fini --noinhibit-exec --output-filetype=yaml -static -o %t
+RUN: FileCheck %s < %t
+
+CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
+CHECK: section-name: .init_array
+CHECK: references:
+CHECK: - kind: R_AARCH64_ABS64
+CHECK: offset: 0
+CHECK: target: init
+CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
+CHECK: section-name: .fini_array
+CHECK: references:
+CHECK: - kind: R_AARCH64_ABS64
+CHECK: offset: 0
+CHECK: target: fini
Added: lld/trunk/test/elf/AArch64/initfini.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/AArch64/initfini.test?rev=215544&view=auto
==============================================================================
--- lld/trunk/test/elf/AArch64/initfini.test (added)
+++ lld/trunk/test/elf/AArch64/initfini.test Wed Aug 13 08:16:38 2014
@@ -0,0 +1,23 @@
+# This tests the functionality that lld is able to read
+# init_array/fini_array sections in the input ELF. This
+# corresponds to the the .init_array/.fini_array sections
+# in the output ELF.
+
+RUN: lld -flavor gnu -target aarch64--linux-gnu %p/Inputs/initfini.o \
+RUN: --noinhibit-exec --output-filetype=yaml -o %t
+RUN: FileCheck %s < %t
+
+CHECK: type: data
+CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
+CHECK: section-name: .init_array
+CHECK: references:
+CHECK: - kind: R_AARCH64_ABS64
+CHECK: offset: 0
+CHECK: target: constructor
+CHECK: type: data
+CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
+CHECK: section-name: .fini_array
+CHECK: references:
+CHECK: - kind: R_AARCH64_ABS64
+CHECK: offset: 0
+CHECK: target: destructor
Modified: lld/trunk/tools/lld/Makefile
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/tools/lld/Makefile?rev=215544&r1=215543&r2=215544&view=diff
==============================================================================
--- lld/trunk/tools/lld/Makefile (original)
+++ lld/trunk/tools/lld/Makefile Wed Aug 13 08:16:38 2014
@@ -23,6 +23,7 @@ USEDLIBS = lldDriver.a \
lldELF.a lldMachO.a lldPasses.a lldPECOFF.a lldYAML.a \
lldReaderWriter.a lldCore.a lldNative.a \
lldHexagonELFTarget.a lldPPCELFTarget.a lldMipsELFTarget.a \
- lldX86ELFTarget.a lldX86_64ELFTarget.a LLVMOption.a
+ lldX86ELFTarget.a lldX86_64ELFTarget.a lldAArch64ELFTarget.a \
+ LLVMOption.a
include $(LLD_LEVEL)/Makefile
Modified: lld/trunk/unittests/DriverTests/Makefile
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/Makefile?rev=215544&r1=215543&r2=215544&view=diff
==============================================================================
--- lld/trunk/unittests/DriverTests/Makefile (original)
+++ lld/trunk/unittests/DriverTests/Makefile Wed Aug 13 08:16:38 2014
@@ -15,5 +15,5 @@ USEDLIBS = lldDriver.a \
lldHexagonELFTarget.a lldPPCELFTarget.a lldMipsELFTarget.a \
lldX86ELFTarget.a lldX86_64ELFTarget.a lldYAML.a \
LLVMObject.a LLVMMCParser.a LLVMMC.a LLVMBitReader.a \
- LLVMCore.a LLVMOption.a LLVMSupport.a
+ LLVMCore.a LLVMOption.a LLVMSupport.a lldAArch64ELFTarget.a
include $(LLD_LEVEL)/unittests/Makefile
More information about the llvm-commits
mailing list