summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt1
-rw-r--r--lld/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h19
-rw-r--r--lld/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp15
-rw-r--r--lld/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp11
-rw-r--r--lld/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp37
-rw-r--r--lld/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.h36
-rw-r--r--lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h19
-rw-r--r--lld/test/elf/X86_64/extern-tls.test16
-rw-r--r--lld/test/elf/gottpoff.test2
-rw-r--r--lld/test/elf/tls.test2
10 files changed, 132 insertions, 26 deletions
diff --git a/lld/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt b/lld/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt
index a85d2b50463..36ea839aa67 100644
--- a/lld/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt
+++ b/lld/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt
@@ -3,6 +3,7 @@ add_llvm_library(lldX86_64ELFTarget
X86_64TargetHandler.cpp
X86_64RelocationHandler.cpp
X86_64RelocationPass.cpp
+ X86_64SectionChunks.cpp
LINK_LIBS
lldELF
lldReaderWriter
diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h b/lld/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h
index 4cea8945fba..930a2de2a9e 100644
--- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h
+++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h
@@ -18,7 +18,7 @@ namespace elf {
class X86_64ExecutableWriter : public ExecutableWriter<ELF64LE> {
public:
X86_64ExecutableWriter(X86_64LinkingContext &ctx, X86_64TargetLayout &layout)
- : ExecutableWriter(ctx, layout) {}
+ : ExecutableWriter(ctx, layout), _targetLayout(layout) {}
protected:
// Add any runtime files and their atoms to the output
@@ -32,6 +32,23 @@ protected:
gotFile->addAtom(*new (gotFile->allocator()) DynamicAtom(*gotFile));
result.push_back(std::move(gotFile));
}
+
+ void buildDynamicSymbolTable(const File &file) override {
+ for (auto sec : this->_layout.sections()) {
+ if (auto section = dyn_cast<AtomSection<ELF64LE>>(sec)) {
+ for (const auto &atom : section->atoms()) {
+ if (_targetLayout.getGOTSection().hasGlobalGOTEntry(atom->_atom)) {
+ this->_dynamicSymbolTable->addSymbol(atom->_atom, section->ordinal(),
+ atom->_virtualAddr, atom);
+ }
+ }
+ }
+ }
+
+ ExecutableWriter<ELF64LE>::buildDynamicSymbolTable(file);
+ }
+
+ X86_64TargetLayout &_targetLayout;
};
} // namespace elf
diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp
index b5f64936aae..d56983d1e38 100644
--- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp
+++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp
@@ -94,18 +94,14 @@ std::error_code X86_64TargetRelocationHandler::applyRelocation(
case R_X86_64_PC16:
relocPC16(loc, reloc, target, ref.addend());
break;
- case R_X86_64_TPOFF64:
case R_X86_64_DTPOFF32:
- case R_X86_64_TPOFF32: {
+ case R_X86_64_TPOFF32:
_tlsSize = _layout.getTLSSize();
- if (ref.kindValue() == R_X86_64_TPOFF32 ||
- ref.kindValue() == R_X86_64_DTPOFF32) {
- write32le(loc, target - _tlsSize);
- } else {
- write64le(loc, target - _tlsSize);
- }
+ write32le(loc, target - _tlsSize);
+ break;
+ case R_X86_64_GOTTPOFF:
+ relocPC32(loc, reloc, target, ref.addend());
break;
- }
case R_X86_64_TLSGD: {
relocPC32(loc, reloc, target, ref.addend());
break;
@@ -141,6 +137,7 @@ std::error_code X86_64TargetRelocationHandler::applyRelocation(
case R_X86_64_GLOB_DAT:
case R_X86_64_DTPMOD64:
case R_X86_64_DTPOFF64:
+ case R_X86_64_TPOFF64:
break;
default:
return make_unhandled_reloc_error();
diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp b/lld/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp
index 64d46f912d5..1be4b9587dc 100644
--- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp
+++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp
@@ -188,11 +188,12 @@ protected:
return got->second;
}
- /// \brief Create a TPOFF64 GOT entry and change the relocation to a PC32 to
- /// the GOT.
- void handleGOTTPOFF(const Reference &ref) {
- const_cast<Reference &>(ref).setTarget(getGOTTPOFF(ref.target()));
- const_cast<Reference &>(ref).setKindValue(R_X86_64_PC32);
+ /// \brief Create a TPOFF64 GOT entry.
+ std::error_code handleGOTTPOFF(const Reference &ref) {
+ if (isa<DefinedAtom>(ref.target())) {
+ const_cast<Reference &>(ref).setTarget(getGOTTPOFF(ref.target()));
+ }
+ return std::error_code();
}
/// \brief Create a TLS GOT entry with DTPMOD64/DTPOFF64 dynamic relocations.
diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp b/lld/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp
new file mode 100644
index 00000000000..28eb3e4244b
--- /dev/null
+++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp
@@ -0,0 +1,37 @@
+//===- lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp --------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "X86_64SectionChunks.h"
+#include "TargetLayout.h"
+
+namespace lld {
+namespace elf {
+
+X86_64GOTSection::X86_64GOTSection(const ELFLinkingContext &ctx)
+ : AtomSection<ELF64LE>(ctx, ".got", DefinedAtom::typeGOT, DefinedAtom::permRW_,
+ TargetLayout<ELF64LE>::ORDER_GOT) {
+ this->_alignment = 8;
+}
+
+const AtomLayout *X86_64GOTSection::appendAtom(const Atom *atom) {
+ const DefinedAtom *da = dyn_cast<DefinedAtom>(atom);
+
+ for (const auto &r : *da) {
+ if (r->kindNamespace() != Reference::KindNamespace::ELF)
+ continue;
+ assert(r->kindArch() == Reference::KindArch::x86_64);
+ if (r->kindValue() == R_X86_64_TPOFF64)
+ _tlsMap[r->target()] = _tlsMap.size();
+ }
+
+ return AtomSection<ELF64LE>::appendAtom(atom);
+}
+
+} // elf
+} // lld
diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.h b/lld/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.h
new file mode 100644
index 00000000000..5208491eee5
--- /dev/null
+++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.h
@@ -0,0 +1,36 @@
+//===- lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.h ----------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_ELF_X86_64_X86_64_SECTION_CHUNKS_H
+#define LLD_READER_WRITER_ELF_X86_64_X86_64_SECTION_CHUNKS_H
+
+#include "TargetLayout.h"
+
+namespace lld {
+namespace elf {
+
+class X86_64GOTSection : public AtomSection<ELF64LE> {
+public:
+ X86_64GOTSection(const ELFLinkingContext &ctx);
+
+ bool hasGlobalGOTEntry(const Atom *a) const {
+ return _tlsMap.count(a);
+ }
+
+ const AtomLayout *appendAtom(const Atom *atom) override;
+
+private:
+ /// \brief Map TLS Atoms to their GOT entry index.
+ llvm::DenseMap<const Atom *, std::size_t> _tlsMap;
+};
+
+} // elf
+} // lld
+
+#endif
diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h
index 53fc15ff023..6e3e58f8aed 100644
--- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h
+++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h
@@ -14,20 +14,34 @@
#include "TargetLayout.h"
#include "X86_64LinkingContext.h"
#include "X86_64RelocationHandler.h"
+#include "X86_64SectionChunks.h"
#include "lld/Core/Simple.h"
namespace lld {
namespace elf {
+
class X86_64TargetLayout : public TargetLayout<ELF64LE> {
public:
- X86_64TargetLayout(X86_64LinkingContext &ctx) : TargetLayout(ctx) {}
+ X86_64TargetLayout(X86_64LinkingContext &ctx) : TargetLayout(ctx),
+ _gotSection(new (this->_allocator) X86_64GOTSection(ctx)) {}
+
+ AtomSection<ELF64LE> *
+ createSection(StringRef name, int32_t type,
+ DefinedAtom::ContentPermissions permissions,
+ TargetLayout<ELF64LE>::SectionOrder order) override {
+ if (type == DefinedAtom::typeGOT && name == ".got")
+ return _gotSection;
+ return TargetLayout<ELF64LE>::createSection(name, type, permissions, order);
+ }
void finalizeOutputSectionLayout() override {
sortOutputSectionByPriority<ELF64LE>(".init_array");
sortOutputSectionByPriority<ELF64LE>(".fini_array");
}
+ const X86_64GOTSection &getGOTSection() const { return *_gotSection; }
+
private:
uint32_t getPriority(StringRef sectionName) const {
StringRef priority = sectionName.drop_front().rsplit('.').second;
@@ -55,6 +69,9 @@ private:
return getPriority(lhsName) < getPriority(rhsName);
});
}
+
+private:
+ X86_64GOTSection *_gotSection;
};
class X86_64TargetHandler : public TargetHandler {
diff --git a/lld/test/elf/X86_64/extern-tls.test b/lld/test/elf/X86_64/extern-tls.test
index 022e86866f8..16a0d5544aa 100644
--- a/lld/test/elf/X86_64/extern-tls.test
+++ b/lld/test/elf/X86_64/extern-tls.test
@@ -3,14 +3,14 @@
RUN: lld -flavor gnu -target x86_64-linux %p/Inputs/externtls.x86-64 -static \
RUN: --output-filetype=yaml --noinhibit-exec | FileCheck %s -check-prefix=CHECKGOT
+# Currently x86_64 relocation pass handles the R_X86_64_GOTTPOFF by
+# creatng R_X86_64_TPOFF64 dynamic ones. For output yaml, this is
+# not changed.
- name: __got_tls_extern_tls
-CHECKGOT: type: got
-CHECKGOT: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
-CHECKGOT: alignment: 8
-CHECKGOT: section-choice: custom-required
-CHECKGOT: section-name: .got
-CHECKGOT: permissions: rw-
+CHECKGOT: alignment: 4
+CHECKGOT: section-name: .text
CHECKGOT: references:
-CHECKGOT: - kind: R_X86_64_TPOFF64
-CHECKGOT: offset: 0
+CHECKGOT: - kind: R_X86_64_GOTTPOFF
+CHECKGOT: offset: 7
CHECKGOT: target: extern_tls
+CHECKGOT: addend: -4
diff --git a/lld/test/elf/gottpoff.test b/lld/test/elf/gottpoff.test
index 9841ee1453d..4a109504dc8 100644
--- a/lld/test/elf/gottpoff.test
+++ b/lld/test/elf/gottpoff.test
@@ -7,7 +7,7 @@
#RUN: llvm-readobj -r %t | FileCheck %s
#
#CHECK: Section (5) .rela.dyn {
-#CHECK: 0x401098 R_X86_64_TPOFF64 - 0x0
+#CHECK: 0x401098 R_X86_64_TPOFF64 tls2 0x0
#CHECK: }
---
diff --git a/lld/test/elf/tls.test b/lld/test/elf/tls.test
index 038889406b6..ff37cadd3d8 100644
--- a/lld/test/elf/tls.test
+++ b/lld/test/elf/tls.test
@@ -22,7 +22,7 @@ YAML: offset: 25
YAML: target: tls2
YAML: name: GOTTPOFF
-YAML: kind: R_X86_64_PC32
+YAML: kind: R_X86_64_GOTTPOFF
YAML: target: [[GOTNAME:[a-zA-Z0-9_]+]]
YAML: type: got
OpenPOWER on IntegriCloud