Index: lib/ReaderWriter/ELF/X86_64/CMakeLists.txt =================================================================== --- lib/ReaderWriter/ELF/X86_64/CMakeLists.txt +++ lib/ReaderWriter/ELF/X86_64/CMakeLists.txt @@ -3,6 +3,7 @@ X86_64TargetHandler.cpp X86_64RelocationHandler.cpp X86_64RelocationPass.cpp + X86_64SectionChunks.cpp LINK_LIBS lldELF lldReaderWriter Index: lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h =================================================================== --- lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h +++ lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h @@ -18,7 +18,7 @@ class X86_64ExecutableWriter : public ExecutableWriter { 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,24 @@ 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>(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::buildDynamicSymbolTable(file); + } + + X86_64TargetLayout &_targetLayout; }; } // namespace elf Index: lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp =================================================================== --- lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp +++ lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp @@ -94,18 +94,14 @@ 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 @@ 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(); Index: lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp =================================================================== --- lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp +++ lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp @@ -188,11 +188,12 @@ 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(ref).setTarget(getGOTTPOFF(ref.target())); - const_cast(ref).setKindValue(R_X86_64_PC32); + /// \brief Create a TPOFF64 GOT entry. + std::error_code handleGOTTPOFF(const Reference &ref) { + if (isa(ref.target())) { + const_cast(ref).setTarget(getGOTTPOFF(ref.target())); + } + return std::error_code(); } /// \brief Create a TLS GOT entry with DTPMOD64/DTPOFF64 dynamic relocations. Index: lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.h =================================================================== --- /dev/null +++ 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 { +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 _tlsMap; +}; + +} // elf +} // lld + +#endif Index: lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp =================================================================== --- /dev/null +++ lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp @@ -0,0 +1,38 @@ +//===- 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(ctx, ".got", DefinedAtom::typeGOT, DefinedAtom::permRW_, + TargetLayout::ORDER_GOT) +{ + this->_alignment = 8; +} + +const AtomLayout *X86_64GOTSection::appendAtom(const Atom *atom) { + const DefinedAtom *da = dyn_cast(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::appendAtom(atom); +} + +} // elf +} // lld Index: lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h =================================================================== --- lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h +++ lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h @@ -14,20 +14,35 @@ #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 { public: - X86_64TargetLayout(X86_64LinkingContext &ctx) : TargetLayout(ctx) {} + X86_64TargetLayout(X86_64LinkingContext &ctx) : TargetLayout(ctx), + _gotSection(new (this->_allocator) X86_64GOTSection(ctx)) {} + + AtomSection * + createSection(StringRef name, int32_t type, + DefinedAtom::ContentPermissions permissions, + TargetLayout::SectionOrder order) override + { + if (type == DefinedAtom::typeGOT && name == ".got") + return _gotSection; + return TargetLayout::createSection(name, type, permissions, order); + } void finalizeOutputSectionLayout() override { sortOutputSectionByPriority(".init_array"); sortOutputSectionByPriority(".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 +70,9 @@ return getPriority(lhsName) < getPriority(rhsName); }); } + +private: + X86_64GOTSection *_gotSection; }; class X86_64TargetHandler : public TargetHandler { Index: test/elf/X86_64/extern-tls.test =================================================================== --- test/elf/X86_64/extern-tls.test +++ 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 Index: test/elf/gottpoff.test =================================================================== --- test/elf/gottpoff.test +++ 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: } --- Index: test/elf/tls.test =================================================================== --- test/elf/tls.test +++ test/elf/tls.test @@ -22,7 +22,7 @@ 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