summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdhemerval Zanella <azanella@linux.vnet.ibm.com>2015-06-03 21:44:03 +0000
committerAdhemerval Zanella <azanella@linux.vnet.ibm.com>2015-06-03 21:44:03 +0000
commit9f0c63bfdfe849095ff8c673f7b6bdb993144fa5 (patch)
tree9706f86935509d2c500fb227bf62e4fcf8d6195e
parent8c52a9b0f611e4daa09c00e0da15b44b9528dbe5 (diff)
downloadbcm5719-llvm-9f0c63bfdfe849095ff8c673f7b6bdb993144fa5.tar.gz
bcm5719-llvm-9f0c63bfdfe849095ff8c673f7b6bdb993144fa5.zip
[ELF/AArch64] Fix TLS initial executable relocation
This patch fixes the TLS initial executable for AArch64. Current implementation have two issues: 1. does not generate dynamic R_AARCH64_TLS_TPREL64 relocation for the external module symbols, and 2. does not export the TLS initial executable symbol in dynamic symbol table. The fix follows the MIPS strategy to add a arch-specific GOTSection class to keep track of TLS symbols required to be place in dynamic symbol table. It also overrides the buildDynamicSymbolTable for ExecutableWrite class to add the symbols. It also adds some refactoring on AArch64RelocationPass.cpp based on ARM backend. llvm-svn: 238981
-rw-r--r--lld/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.cpp50
-rw-r--r--lld/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h25
-rw-r--r--lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp1
-rw-r--r--lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp51
-rw-r--r--lld/lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.cpp38
-rw-r--r--lld/lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.h36
-rw-r--r--lld/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp14
-rw-r--r--lld/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h12
-rw-r--r--lld/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt2
-rw-r--r--lld/test/elf/AArch64/Inputs/initial-exec-tls-1.yaml78
-rw-r--r--lld/test/elf/AArch64/initial-exec-tls-0.test147
11 files changed, 418 insertions, 36 deletions
diff --git a/lld/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.cpp b/lld/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.cpp
new file mode 100644
index 00000000000..ba4259479a8
--- /dev/null
+++ b/lld/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.cpp
@@ -0,0 +1,50 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.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 "AArch64ExecutableWriter.h"
+#include "AArch64TargetHandler.h"
+#include "AArch64SectionChunks.h"
+
+namespace lld {
+namespace elf {
+
+AArch64ExecutableWriter::AArch64ExecutableWriter(AArch64LinkingContext &ctx,
+ AArch64TargetLayout &layout)
+ : ExecutableWriter(ctx, layout), _targetLayout(layout) {}
+
+void AArch64ExecutableWriter::createImplicitFiles(
+ std::vector<std::unique_ptr<File>> &result) {
+ ExecutableWriter::createImplicitFiles(result);
+ 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));
+}
+
+void AArch64ExecutableWriter::buildDynamicSymbolTable(const File &file) {
+ 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);
+ continue;
+ }
+ }
+ }
+ }
+
+ ExecutableWriter<ELF64LE>::buildDynamicSymbolTable(file);
+}
+
+} // namespace elf
+} // namespace lld
+
diff --git a/lld/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h b/lld/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h
index c3d9ed24e25..eef825040ff 100644
--- a/lld/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h
+++ b/lld/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h
@@ -9,35 +9,28 @@
#ifndef AARCH64_EXECUTABLE_WRITER_H
#define AARCH64_EXECUTABLE_WRITER_H
-#include "AArch64LinkingContext.h"
#include "ExecutableWriter.h"
namespace lld {
namespace elf {
+class AArch64TargetLayout;
+class AArch64LinkingContext;
+
class AArch64ExecutableWriter : public ExecutableWriter<ELF64LE> {
public:
AArch64ExecutableWriter(AArch64LinkingContext &ctx,
- TargetLayout<ELF64LE> &layout);
+ AArch64TargetLayout &layout);
protected:
// Add any runtime files and their atoms to the output
void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
-};
-AArch64ExecutableWriter::AArch64ExecutableWriter(AArch64LinkingContext &ctx,
- TargetLayout<ELF64LE> &layout)
- : ExecutableWriter(ctx, layout) {}
-
-void AArch64ExecutableWriter::createImplicitFiles(
- std::vector<std::unique_ptr<File>> &result) {
- ExecutableWriter::createImplicitFiles(result);
- 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));
-}
+ void buildDynamicSymbolTable(const File &file) override;
+
+private:
+ AArch64TargetLayout &_targetLayout;
+};
} // namespace elf
} // namespace lld
diff --git a/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp
index b80bc21976a..5c425d0dc65 100644
--- a/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp
+++ b/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp
@@ -433,6 +433,7 @@ std::error_code AArch64TargetRelocationHandler::applyRelocation(
case R_AARCH64_IRELATIVE:
case R_AARCH64_JUMP_SLOT:
case R_AARCH64_GLOB_DAT:
+ case R_AARCH64_TLS_TPREL64:
break;
case R_AARCH64_ADR_PREL_PG_HI21:
return relocR_AARCH64_ADR_PREL_PG_HI21(loc, reloc, target, addend);
diff --git a/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp b/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp
index 03a3ce1fc05..2614a03dfbf 100644
--- a/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp
+++ b/lld/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp
@@ -56,11 +56,20 @@ namespace {
/// \brief Atoms that are used by AArch64 dynamic linking
class AArch64GOTAtom : public GOTAtom {
public:
- AArch64GOTAtom(const File &f, StringRef secName) : GOTAtom(f, secName) {}
+ AArch64GOTAtom(const File &f) : GOTAtom(f, ".got") {}
ArrayRef<uint8_t> rawContent() const override {
return ArrayRef<uint8_t>(AArch64GotAtomContent, 8);
}
+
+protected:
+ // Constructor for AArch64GOTAtom
+ AArch64GOTAtom(const File &f, StringRef secName) : GOTAtom(f, secName) {}
+};
+
+class AArch64GOTPLTAtom : public AArch64GOTAtom {
+public:
+ AArch64GOTPLTAtom(const File &f) : AArch64GOTAtom(f, ".got.plt") {}
};
class AArch64PLT0Atom : public PLT0Atom {
@@ -73,7 +82,7 @@ public:
class AArch64PLTAtom : public PLTAtom {
public:
- AArch64PLTAtom(const File &f, StringRef secName) : PLTAtom(f, secName) {}
+ AArch64PLTAtom(const File &f) : PLTAtom(f, ".plt") {}
ArrayRef<uint8_t> rawContent() const override {
return ArrayRef<uint8_t>(AArch64PltAtomContent, 16);
@@ -138,9 +147,11 @@ template <class Derived> class AArch64RelocationPass : public Pass {
break;
case R_AARCH64_ADR_GOT_PAGE:
case R_AARCH64_LD64_GOT_LO12_NC:
+ static_cast<Derived *>(this)->handleGOT(ref);
+ break;
case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
- static_cast<Derived *>(this)->handleGOT(ref);
+ static_cast<Derived *>(this)->handleGOTTPREL(ref);
break;
}
}
@@ -153,9 +164,9 @@ protected:
auto plt = _pltMap.find(da);
if (plt != _pltMap.end())
return plt->second;
- auto ga = new (_file._alloc) AArch64GOTAtom(_file, ".got.plt");
+ auto ga = new (_file._alloc) AArch64GOTPLTAtom(_file);
ga->addReferenceELF_AArch64(R_AARCH64_IRELATIVE, 0, da, 0);
- auto pa = new (_file._alloc) AArch64PLTAtom(_file, ".plt");
+ auto pa = new (_file._alloc) AArch64PLTAtom(_file);
pa->addReferenceELF_AArch64(R_AARCH64_PREL32, 2, ga, -4);
#ifndef NDEBUG
ga->_name = "__got_ifunc_";
@@ -182,11 +193,11 @@ protected:
}
/// \brief Create a GOT entry for the TP offset of a TLS atom.
- const GOTAtom *getGOTTPOFF(const Atom *atom) {
+ const GOTAtom *getGOTTPREL(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);
+ auto g = new (_file._alloc) AArch64GOTAtom(_file);
+ g->addReferenceELF_AArch64(R_AARCH64_TLS_TPREL64, 0, atom, 0);
#ifndef NDEBUG
g->_name = "__got_tls_";
g->_name += atom->name();
@@ -198,17 +209,19 @@ protected:
return got->second;
}
- /// \brief Create a TPOFF64 GOT entry and change the relocation to a PC32 to
+ /// \brief Create a GOT TPREL 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);
+ std::error_code handleGOTTPREL(const Reference &ref) {
+ if (isa<DefinedAtom>(ref.target())) {
+ const_cast<Reference &>(ref).setTarget(getGOTTPREL(ref.target()));
+ }
+ return std::error_code();
}
/// \brief Create a GOT entry containing 0.
const GOTAtom *getNullGOT() {
if (!_null) {
- _null = new (_file._alloc) AArch64GOTAtom(_file, ".got.plt");
+ _null = new (_file._alloc) AArch64GOTPLTAtom(_file);
#ifndef NDEBUG
_null->_name = "__got_null";
#endif
@@ -219,7 +232,7 @@ protected:
const GOTAtom *getGOT(const DefinedAtom *da) {
auto got = _gotMap.find(da);
if (got == _gotMap.end()) {
- auto g = new (_file._alloc) AArch64GOTAtom(_file, ".got");
+ auto g = new (_file._alloc) AArch64GOTAtom(_file);
g->addReferenceELF_AArch64(R_AARCH64_ABS64, 0, da, 0);
#ifndef NDEBUG
g->_name = "__got_";
@@ -386,8 +399,8 @@ public:
// 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");
+ _got0 = new (_file._alloc) AArch64GOTPLTAtom(_file);
+ _got1 = new (_file._alloc) AArch64GOTPLTAtom(_file);
_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);
@@ -403,9 +416,9 @@ public:
auto plt = _pltMap.find(a);
if (plt != _pltMap.end())
return plt->second;
- auto ga = new (_file._alloc) AArch64GOTAtom(_file, ".got.plt");
+ auto ga = new (_file._alloc) AArch64GOTPLTAtom(_file);
ga->addReferenceELF_AArch64(R_AARCH64_JUMP_SLOT, 0, a, 0);
- auto pa = new (_file._alloc) AArch64PLTAtom(_file, ".plt");
+ auto pa = new (_file._alloc) AArch64PLTAtom(_file);
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);
@@ -472,7 +485,7 @@ public:
const GOTAtom *getSharedGOT(const SharedLibraryAtom *sla) {
auto got = _gotMap.find(sla);
if (got == _gotMap.end()) {
- auto g = new (_file._alloc) AArch64GOTAtom(_file, ".got");
+ auto g = new (_file._alloc) AArch64GOTAtom(_file);
g->addReferenceELF_AArch64(R_AARCH64_GLOB_DAT, 0, sla, 0);
#ifndef NDEBUG
g->_name = "__got_";
diff --git a/lld/lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.cpp b/lld/lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.cpp
new file mode 100644
index 00000000000..ee8a8110d6f
--- /dev/null
+++ b/lld/lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.cpp
@@ -0,0 +1,38 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.cpp --------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AArch64SectionChunks.h"
+#include "TargetLayout.h"
+
+namespace lld {
+namespace elf {
+
+AArch64GOTSection::AArch64GOTSection(const ELFLinkingContext &ctx)
+ : AtomSection<ELF64LE>(ctx, ".got", DefinedAtom::typeGOT, DefinedAtom::permRW_,
+ TargetLayout<ELF64LE>::ORDER_GOT)
+{
+ this->_alignment = 8;
+}
+
+const AtomLayout *AArch64GOTSection::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::AArch64);
+ if (r->kindValue() == R_AARCH64_TLS_TPREL64)
+ _tlsMap[r->target()] = _tlsMap.size();
+ }
+
+ return AtomSection<ELF64LE>::appendAtom(atom);
+}
+
+} // elf
+} // lld
diff --git a/lld/lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.h b/lld/lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.h
new file mode 100644
index 00000000000..84533dd7c93
--- /dev/null
+++ b/lld/lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.h
@@ -0,0 +1,36 @@
+//===- lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.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_SECTION_CHUNKS_H
+#define LLD_READER_WRITER_ELF_AARCH64_AARCH64_SECTION_CHUNKS_H
+
+#include "TargetLayout.h"
+
+namespace lld {
+namespace elf {
+
+class AArch64GOTSection : public AtomSection<ELF64LE> {
+public:
+ AArch64GOTSection(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/lld/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp b/lld/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp
index 1d8b7add115..fa83cf9ecc4 100644
--- a/lld/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp
+++ b/lld/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp
@@ -12,10 +12,24 @@
#include "AArch64ExecutableWriter.h"
#include "AArch64LinkingContext.h"
#include "AArch64TargetHandler.h"
+#include "AArch64SectionChunks.h"
using namespace lld;
using namespace elf;
+AArch64TargetLayout::AArch64TargetLayout(ELFLinkingContext &ctx) :
+ TargetLayout(ctx),
+ _gotSection(new (this->_allocator) AArch64GOTSection(ctx)) {}
+
+AtomSection<ELF64LE> *AArch64TargetLayout::createSection(
+ StringRef name, int32_t type, DefinedAtom::ContentPermissions permissions,
+ typename TargetLayout<ELF64LE>::SectionOrder order) {
+ if (type == DefinedAtom::typeGOT && name == ".got")
+ return _gotSection;
+ return TargetLayout<ELF64LE>::createSection(name, type, permissions, order);
+}
+
+
AArch64TargetHandler::AArch64TargetHandler(AArch64LinkingContext &ctx)
: _ctx(ctx), _targetLayout(new AArch64TargetLayout(ctx)),
_relocationHandler(new AArch64TargetRelocationHandler(*_targetLayout)) {}
diff --git a/lld/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h b/lld/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h
index aac46171660..6f077e6a5ee 100644
--- a/lld/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h
+++ b/lld/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h
@@ -17,13 +17,22 @@
namespace lld {
namespace elf {
+
class AArch64LinkingContext;
+class AArch64GOTSection;
class AArch64TargetLayout final : public TargetLayout<ELF64LE> {
typedef llvm::object::Elf_Shdr_Impl<ELF64LE> Elf_Shdr;
public:
- AArch64TargetLayout(ELFLinkingContext &ctx) : TargetLayout(ctx) {}
+ AArch64TargetLayout(ELFLinkingContext &ctx);
+
+ AtomSection<ELF64LE> *
+ createSection(StringRef name, int32_t type,
+ DefinedAtom::ContentPermissions permissions,
+ typename TargetLayout<ELF64LE>::SectionOrder order) override;
+
+ const AArch64GOTSection &getGOTSection() const { return *_gotSection; }
uint64_t getTPOffset() {
std::call_once(_tpOffOnce, [this]() {
@@ -44,6 +53,7 @@ private:
};
private:
+ AArch64GOTSection *_gotSection;
uint64_t _tpOff = 0;
std::once_flag _tpOffOnce;
};
diff --git a/lld/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt b/lld/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt
index de94a4df507..2347dda9adb 100644
--- a/lld/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt
+++ b/lld/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt
@@ -3,6 +3,8 @@ add_llvm_library(lldAArch64ELFTarget
AArch64TargetHandler.cpp
AArch64RelocationHandler.cpp
AArch64RelocationPass.cpp
+ AArch64ExecutableWriter.cpp
+ AArch64SectionChunks.cpp
LINK_LIBS
lldELF
lldReaderWriter
diff --git a/lld/test/elf/AArch64/Inputs/initial-exec-tls-1.yaml b/lld/test/elf/AArch64/Inputs/initial-exec-tls-1.yaml
new file mode 100644
index 00000000000..564292bedad
--- /dev/null
+++ b/lld/test/elf/AArch64/Inputs/initial-exec-tls-1.yaml
@@ -0,0 +1,78 @@
+---
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ OSABI: ELFOSABI_GNU
+ Type: ET_REL
+ Machine: EM_AARCH64
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x0000000000000004
+ Content: ''
+ - Name: .data
+ Type: SHT_PROGBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ AddressAlign: 0x0000000000000004
+ Content: ''
+ - Name: .bss
+ Type: SHT_NOBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ AddressAlign: 0x0000000000000004
+ Content: ''
+ - Name: .tbss
+ Type: SHT_NOBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
+ AddressAlign: 0x0000000000000004
+ Content: 00636C616E672076657273696F6E2033
+ - Name: .comment
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 00636C616E672076657273696F6E20332E372E302028687474703A2F2F6C6C766D2E6F72672F6769742F636C616E672E6769742065653461393664373236383264353237636635353336313135366235656531383662303964363138292028687474703A2F2F6C6C766D2E6F72672F6769742F6C6C766D2E67697420623065376165623639343236646331346637376466626535343533333536366664363866396466632900
+ - Name: .note.GNU-stack
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: ''
+Symbols:
+ Local:
+ - Name: '$d.0'
+ Type: STT_TLS
+ Section: .tbss
+ - Name: '$d.1'
+ Section: .comment
+ - Name: .tbss
+ Type: STT_TLS
+ Section: .tbss
+ - Type: STT_SECTION
+ Section: .text
+ - Type: STT_SECTION
+ Section: .data
+ - Type: STT_SECTION
+ Section: .bss
+ - Type: STT_SECTION
+ Section: .comment
+ - Type: STT_SECTION
+ Section: .note.GNU-stack
+ Global:
+ - Name: e0
+ Type: STT_TLS
+ Section: .tbss
+ Size: 0x0000000000000004
+ - Name: e1
+ Type: STT_TLS
+ Section: .tbss
+ Value: 0x0000000000000004
+ Size: 0x0000000000000004
+ - Name: e2
+ Type: STT_TLS
+ Section: .tbss
+ Value: 0x0000000000000008
+ Size: 0x0000000000000004
+ - Name: e3
+ Type: STT_TLS
+ Section: .tbss
+ Value: 0x000000000000000C
+ Size: 0x0000000000000004
+...
diff --git a/lld/test/elf/AArch64/initial-exec-tls-0.test b/lld/test/elf/AArch64/initial-exec-tls-0.test
new file mode 100644
index 00000000000..d4da2f9b112
--- /dev/null
+++ b/lld/test/elf/AArch64/initial-exec-tls-0.test
@@ -0,0 +1,147 @@
+# Check for initial executable TLS access across different modules. For
+# this case compiler will emit R_AARCH64_TLSLD_ADR_PAGE21 and
+# R_AARCH64_TLSLD_ADD_LO12_NC static relocations and linker should create
+# a R_AARCH64_TLS_TPREL64 dynamic relocation for variable access.
+
+# The test case was generated from following code snippet:
+#
+# t1.c (initial-exec-tls-1.yaml)
+#
+# __thread int e0;
+# __thread int e1;
+# __thread int e2;
+# __thread int e3;
+#
+# t0.c (initial-exec-tls-0.test)
+#
+# extern __thread int e0;
+# extern __thread int e1;
+# extern __thread int e2;
+# extern __thread int e3;
+#
+# int main ()
+# {
+# e0 = 1;
+# e1 = 2;
+# e1 = 3;
+# e1 = 4;
+# }
+
+#RUN: yaml2obj -format=elf %p/Inputs/initial-exec-tls-1.yaml -o=%t-t1.o
+#RUN: yaml2obj -format=elf %s -o %t-t0.o
+#RUN: lld -flavor gnu -target arm64 --noinhibit-exec -o %t.exe %t-t0.o %t-t1.o
+#RUN: llvm-readobj -relocations %t.exe | FileCheck %s -check-prefix=CHECKRELOCATION
+#RUN: llvm-objdump -s -t %t.exe | FileCheck %s
+
+#CHECKRELOCATION: R_AARCH64_TLS_TPREL64 e0 0x0
+#CHECKRELOCATION: R_AARCH64_TLS_TPREL64 e1 0x0
+#CHECKRELOCATION: R_AARCH64_TLS_TPREL64 e2 0x0
+#CHECKRELOCATION: R_AARCH64_TLS_TPREL64 e3 0x0
+
+#CHECK: Contents of section .text:
+#CHECK-NEXT: 4002c0 ff4300d1 e8031f2a e9031e32 0a0000b0 .C.....*...2....
+# \_ adrp x10, 401000 (R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21)
+#CHECK-NEXT: 4002d0 4a4940f9 4bd03bd5 ec030032 6c692ab8 JI@.K.;....2li*.
+# \_ ldr x10, [x10,#144] (R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC)
+#CHECK-NEXT: 4002e0 0a0000b0 4a4d40f9 ec031f32 6c692ab8 ....JM@....2li*.
+# \_ | adrp x10, 401000 (R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21)
+# \_ ldr x10, [x10,#152] (R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC)
+#CHECK-NEXT: 4002f0 0a0000b0 4a5140f9 ec070032 6c692ab8 ....JQ@....2li*.
+# \_ | adrp x10, 401000 (R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21)
+# \_ ldr x10, [x10,#160] (R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC)
+#CHECK-NEXT: 400300 0a0000b0 4a5540f9 ec031e32 6c692ab8 ....JU@....2li*.
+# \_ | adrp x10, 401000 (R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21)
+# \_ ldr x10, [x10,#168] (R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC)
+
+---
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ OSABI: ELFOSABI_GNU
+ Type: ET_REL
+ Machine: EM_AARCH64
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x0000000000000004
+ Content: FF4300D1E8031F2AE9031E320A0000904A0140F94BD03BD5EC0300326C692AB80A0000904A0140F9EC031F326C692AB80A0000904A0140F9EC0700326C692AB80A0000904A0140F9EC031E326C692AB8E003082AE90F00B9FF430091C0035FD6
+ - Name: .rela.text
+ Type: SHT_RELA
+ Link: .symtab
+ AddressAlign: 0x0000000000000008
+ Info: .text
+ Relocations:
+ - Offset: 0x000000000000000C
+ Symbol: e0
+ Type: R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21
+ - Offset: 0x0000000000000010
+ Symbol: e0
+ Type: R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC
+ - Offset: 0x0000000000000020
+ Symbol: e1
+ Type: R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21
+ - Offset: 0x0000000000000024
+ Symbol: e1
+ Type: R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC
+ - Offset: 0x0000000000000030
+ Symbol: e2
+ Type: R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21
+ - Offset: 0x0000000000000034
+ Symbol: e2
+ Type: R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC
+ - Offset: 0x0000000000000040
+ Symbol: e3
+ Type: R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21
+ - Offset: 0x0000000000000044
+ Symbol: e3
+ Type: R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC
+ - Name: .data
+ Type: SHT_PROGBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ AddressAlign: 0x0000000000000004
+ Content: ''
+ - Name: .bss
+ Type: SHT_NOBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ AddressAlign: 0x0000000000000004
+ Content: ''
+ - Name: .comment
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 00636C616E672076657273696F6E20332E372E302028687474703A2F2F6C6C766D2E6F72672F6769742F636C616E672E6769742065653461393664373236383264353237636635353336313135366235656531383662303964363138292028687474703A2F2F6C6C766D2E6F72672F6769742F6C6C766D2E67697420623065376165623639343236646331346637376466626535343533333536366664363866396466632900
+ - Name: .note.GNU-stack
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: ''
+Symbols:
+ Local:
+ - Name: '$d.1'
+ Section: .comment
+ - Name: '$x.0'
+ Section: .text
+ - Type: STT_SECTION
+ Section: .text
+ - Type: STT_SECTION
+ Section: .data
+ - Type: STT_SECTION
+ Section: .bss
+ - Type: STT_SECTION
+ Section: .comment
+ - Type: STT_SECTION
+ Section: .note.GNU-stack
+ Global:
+ - Name: e0
+ Type: STT_TLS
+ - Name: e1
+ Type: STT_TLS
+ - Name: e2
+ Type: STT_TLS
+ - Name: e3
+ Type: STT_TLS
+ - Name: main
+ Type: STT_FUNC
+ Section: .text
+ Size: 0x0000000000000060
+...
OpenPOWER on IntegriCloud