[lld] r218633 - [lld] [ELF] Support for general dynamic TLS relocations on X86_64

Roman Divacky rdivacky at vlakno.cz
Tue Sep 30 11:21:39 PDT 2014


With this commit, I am able to link a working llc (ie. nontrivial,
in fact huge, binary) on FreeBSD/amd64. This is a great success
and makes lld very interesting from the FreeBSDs point of view.

Thank you Rafael and all those involved to make this happen!

Roman

On Mon, Sep 29, 2014 at 10:05:27PM -0000, Rafael Auler wrote:
> Author: rafauler
> Date: Mon Sep 29 17:05:26 2014
> New Revision: 218633
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=218633&view=rev
> Log:
> [lld] [ELF] Support for general dynamic TLS relocations on X86_64
> 
> Summary:
> This patch adds support for the general dynamic TLS access model for X86_64 (see www.akkadia.org/drepper/tls.pdf).
> 
> To properly support TLS, the patch also changes the __tls_get_addr atom to be a shared library atom instead of a regularly defined atom (the previous lld approach). This closely models the reality of a function that will be resolved at runtime by the dynamic linker and loader itself (ld.so). I was tempted to force LLD to link against ld.so itself to resolve these symbols, but since GNU ld does not need the ld.so library to resolve this symbol, I decided to mimic its behavior and keep hardwired a definition of __tls_get_addr in the lld code.
> 
> This patch also moves some important logic that previously was only available to the MIPS lld backend to be used to all ELF backends. This logic, which now lives in the DefaultLayout class, will monitor which external (shared lib) symbols are really imported by the current module and will only populate the dynamic symbol table with used symbols, as opposed to the previous approach of dumping all shared lib symbols in the dynamic symbol table. This is important to this patch to avoid __tls_get_addr from getting injected into all dynamic symbol tables.
> 
> By solving the previous problem of always adding __tls_get_addr, now the produced symbol tables are slightly smaller. But this impacted several tests that relied on hardwired/predefined sizes of the symbol table, requiring this patch to update such tests.
> 
> Test Plan: Added a LIT test case that exercises a simple use case of TLS variable in a shared library.
> 
> Reviewers: ruiu, rafael, Bigcheese, shankarke
> 
> Reviewed By: Bigcheese, shankarke
> 
> Subscribers: emaste, shankarke, joerg, kledzik, mcrosier, llvm-commits
> 
> Projects: #lld
> 
> Differential Revision: http://reviews.llvm.org/D5505
> 
> Added:
>     lld/trunk/test/elf/X86_64/Inputs/generaltls-so.o.yaml
>     lld/trunk/test/elf/X86_64/general-dynamic-tls.test
> Modified:
>     lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h
>     lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h
>     lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h
>     lld/trunk/lib/ReaderWriter/ELF/Atoms.h
>     lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h
>     lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
>     lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h
>     lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h
>     lld/trunk/lib/ReaderWriter/ELF/TODO.txt
>     lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64DynamicLibraryWriter.h
>     lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h
>     lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h
>     lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp
>     lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp
>     lld/trunk/test/elf/X86_64/omagic.test
>     lld/trunk/test/elf/X86_64/undef.test
>     lld/trunk/test/elf/X86_64/underscore-end.test
>     lld/trunk/test/elf/dynamic-segorder.test
>     lld/trunk/test/elf/dynamic-undef.test
>     lld/trunk/test/elf/undef-from-main-dso.test
> 
> Modified: lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h?rev=218633&r1=218632&r2=218633&view=diff
> ==============================================================================
> --- lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h (original)
> +++ lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h Mon Sep 29 17:05:26 2014
> @@ -262,8 +262,8 @@ public:
>  
>    void setCreateSeparateROSegment() { _mergeRODataToTextSegment = false; }
>  
> -  bool hasCoalescedSharedLibPair(StringRef name) const {
> -    return _sharedLibCoalescedSymbols.count(name) != 0;
> +  bool isDynamicallyExportedSymbol(StringRef name) const {
> +    return _dynamicallyExportedSymbols.count(name) != 0;
>    }
>  
>  private:
> @@ -300,7 +300,7 @@ protected:
>    StringRefVector _rpathList;
>    StringRefVector _rpathLinkList;
>    std::map<std::string, uint64_t> _absoluteSymbols;
> -  llvm::StringSet<> _sharedLibCoalescedSymbols;
> +  llvm::StringSet<> _dynamicallyExportedSymbols;
>  };
>  } // end namespace lld
>  
> 
> Modified: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h?rev=218633&r1=218632&r2=218633&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h Mon Sep 29 17:05:26 2014
> @@ -57,7 +57,6 @@ bool AArch64DynamicLibraryWriter<ELFT>::
>      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;
> 
> Modified: lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h?rev=218633&r1=218632&r2=218633&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h Mon Sep 29 17:05:26 2014
> @@ -56,7 +56,6 @@ bool AArch64ExecutableWriter<ELFT>::crea
>      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));
> 
> Modified: lld/trunk/lib/ReaderWriter/ELF/Atoms.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Atoms.h?rev=218633&r1=218632&r2=218633&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/ELF/Atoms.h (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/Atoms.h Mon Sep 29 17:05:26 2014
> @@ -820,31 +820,6 @@ public:
>    ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
>  };
>  
> -class TLSGETADDRAtom : public SimpleELFDefinedAtom {
> -public:
> -  TLSGETADDRAtom(const File &f) : SimpleELFDefinedAtom(f) {}
> -
> -  StringRef name() const override { return "__tls_get_addr"; }
> -
> -  Scope scope() const override { return scopeGlobal; }
> -
> -  Merge merge() const override { return mergeAsWeak; }
> -
> -  SectionChoice sectionChoice() const override { return sectionCustomRequired; }
> -
> -  StringRef customSectionName() const override { return ".text"; }
> -
> -  ContentType contentType() const override { return typeCode; }
> -
> -  uint64_t size() const override { return 0; }
> -
> -  ContentPermissions permissions() const override { return permR_X; }
> -
> -  Alignment alignment() const override { return Alignment(0); }
> -
> -  ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
> -};
> -
>  class DYNAMICAtom : public SimpleELFDefinedAtom {
>  public:
>    DYNAMICAtom(const File &f) : SimpleELFDefinedAtom(f) {}
> 
> Modified: lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h?rev=218633&r1=218632&r2=218633&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/DefaultLayout.h Mon Sep 29 17:05:26 2014
> @@ -21,6 +21,7 @@
>  
>  #include "llvm/ADT/ArrayRef.h"
>  #include "llvm/ADT/DenseMap.h"
> +#include "llvm/ADT/DenseSet.h"
>  #include "llvm/ADT/Hashing.h"
>  #include "llvm/ADT/SmallVector.h"
>  #include "llvm/ADT/StringExtras.h"
> @@ -296,6 +297,10 @@ public:
>      return 0;
>    }
>  
> +  bool isReferencedByDefinedAtom(const SharedLibraryAtom *sla) const {
> +    return _referencedDynAtoms.count(sla);
> +  }
> +
>  protected:
>    /// \brief Allocate a new section.
>    virtual AtomSection<ELFT> *createSection(
> @@ -317,6 +322,7 @@ protected:
>    LLD_UNIQUE_BUMP_PTR(RelocationTable<ELFT>) _dynamicRelocationTable;
>    LLD_UNIQUE_BUMP_PTR(RelocationTable<ELFT>) _pltRelocationTable;
>    std::vector<lld::AtomLayout *> _absoluteAtoms;
> +  llvm::DenseSet<const SharedLibraryAtom *> _referencedDynAtoms;
>    const ELFLinkingContext &_context;
>  };
>  
> @@ -556,11 +562,14 @@ ErrorOr<const lld::AtomLayout &> Default
>      AtomSection<ELFT> *section =
>          getSection(sectionName, contentType, permissions);
>      // Add runtime relocations to the .rela section.
> -    for (const auto &reloc : *definedAtom)
> +    for (const auto &reloc : *definedAtom) {
>        if (_context.isDynamicRelocation(*definedAtom, *reloc))
>          getDynamicRelocationTable()->addRelocation(*definedAtom, *reloc);
>        else if (_context.isPLTRelocation(*definedAtom, *reloc))
>          getPLTRelocationTable()->addRelocation(*definedAtom, *reloc);
> +      if (const auto *sla = dyn_cast<SharedLibraryAtom>(reloc->target()))
> +        _referencedDynAtoms.insert(sla);
> +    }
>      return section->appendAtom(atom);
>    } else if (const AbsoluteAtom *absoluteAtom = dyn_cast<AbsoluteAtom>(atom)) {
>      // Absolute atoms are not part of any section, they are global for the whole
> 
> Modified: lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp?rev=218633&r1=218632&r2=218633&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp Mon Sep 29 17:05:26 2014
> @@ -259,7 +259,7 @@ void ELFLinkingContext::notifySymbolTabl
>      // If strong defined atom coalesces away an atom declared
>      // in the shared object the strong atom needs to be dynamically exported.
>      // Save its name.
> -    _sharedLibCoalescedSymbols.insert(ua->name());
> +    _dynamicallyExportedSymbols.insert(ua->name());
>  }
>  
>  } // end namespace lld
> 
> Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h?rev=218633&r1=218632&r2=218633&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h Mon Sep 29 17:05:26 2014
> @@ -68,9 +68,6 @@ public:
>      // 2. Set of shared library atoms have corresponding R_MIPS_COPY copies.
>      if (const auto *da = dyn_cast<DefinedAtom>(atom))
>        for (const Reference *ref : *da) {
> -        if (const auto *sla = dyn_cast<SharedLibraryAtom>(ref->target()))
> -          _referencedDynAtoms.insert(sla);
> -
>          if (ref->kindNamespace() == lld::Reference::KindNamespace::ELF) {
>            assert(ref->kindArch() == Reference::KindArch::Mips);
>            if (ref->kindValue() == llvm::ELF::R_MIPS_COPY)
> @@ -81,10 +78,6 @@ public:
>      return TargetLayout<ELFType>::addAtom(atom);
>    }
>  
> -  bool isReferencedByDefinedAtom(const SharedLibraryAtom *sla) const {
> -    return _referencedDynAtoms.count(sla);
> -  }
> -
>    bool isCopied(const SharedLibraryAtom *sla) const {
>      return _copiedDynSymNames.count(sla->name());
>    }
> @@ -116,7 +109,6 @@ private:
>    MipsPLTSection<ELFType> *_pltSection;
>    llvm::Optional<AtomLayout *> _gpAtom;
>    llvm::Optional<AtomLayout *> _gpDispAtom;
> -  llvm::DenseSet<const SharedLibraryAtom *> _referencedDynAtoms;
>    llvm::StringSet<> _copiedDynSymNames;
>  };
>  
> 
> Modified: lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h?rev=218633&r1=218632&r2=218633&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h Mon Sep 29 17:05:26 2014
> @@ -110,7 +110,7 @@ protected:
>  
>    /// \brief Create entry in the dynamic symbols table for this atom.
>    virtual bool isDynSymEntryRequired(const SharedLibraryAtom *sla) const {
> -    return true;
> +    return _layout.isReferencedByDefinedAtom(sla);
>    }
>  
>    /// \brief Create DT_NEEDED dynamic tage for the shared library.
> @@ -183,7 +183,7 @@ void OutputELFWriter<ELFT>::buildDynamic
>        for (const auto &atom : section->atoms()) {
>          const DefinedAtom *da = dyn_cast<const DefinedAtom>(atom->_atom);
>          if (da && (da->dynamicExport() == DefinedAtom::dynamicExportAlways ||
> -                   _context.hasCoalescedSharedLibPair(da->name())))
> +                   _context.isDynamicallyExportedSymbol(da->name())))
>            _dynamicSymbolTable->addSymbol(atom->_atom, section->ordinal(),
>                                           atom->_virtualAddr, atom);
>        }
> 
> Modified: lld/trunk/lib/ReaderWriter/ELF/TODO.txt
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/TODO.txt?rev=218633&r1=218632&r2=218633&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/ELF/TODO.txt (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/TODO.txt Mon Sep 29 17:05:26 2014
> @@ -8,8 +8,6 @@ lib/ReaderWriter/ELF
>  
>  - _GLOBAL_OFFSET_TABLE should be hidden and normally dropped from the output.
>  
> -- Find out where __tls_get_addr gets created and stop that.
> -
>  - Preserve SHT_NOTE sections from input, merge them if applicable.
>  
>  - Do not create __got_* / __plt_* symbol table entries by default.
> 
> Modified: lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64DynamicLibraryWriter.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64DynamicLibraryWriter.h?rev=218633&r1=218632&r2=218633&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64DynamicLibraryWriter.h (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64DynamicLibraryWriter.h Mon Sep 29 17:05:26 2014
> @@ -57,7 +57,6 @@ bool X86_64DynamicLibraryWriter<ELFT>::c
>      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;
> 
> Modified: lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h?rev=218633&r1=218632&r2=218633&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h Mon Sep 29 17:05:26 2014
> @@ -56,7 +56,6 @@ bool X86_64ExecutableWriter<ELFT>::creat
>      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));
> 
> Modified: lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h?rev=218633&r1=218632&r2=218633&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h Mon Sep 29 17:05:26 2014
> @@ -50,6 +50,8 @@ public:
>      case llvm::ELF::R_X86_64_RELATIVE:
>      case llvm::ELF::R_X86_64_GLOB_DAT:
>      case llvm::ELF::R_X86_64_COPY:
> +    case llvm::ELF::R_X86_64_DTPMOD64:
> +    case llvm::ELF::R_X86_64_DTPOFF64:
>        return true;
>      default:
>        return false;
> 
> Modified: lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp?rev=218633&r1=218632&r2=218633&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp Mon Sep 29 17:05:26 2014
> @@ -88,6 +88,10 @@ std::error_code X86_64TargetRelocationHa
>      }
>      break;
>    }
> +  case R_X86_64_TLSGD: {
> +    relocPC32(location, relocVAddress, targetVAddress, ref.addend());
> +    break;
> +  }
>    case R_X86_64_TLSLD: {
>      // Rewrite to move %fs:0 into %rax. Technically we should verify that the
>      // next relocation is a PC32 to __tls_get_addr...
> @@ -115,6 +119,8 @@ std::error_code X86_64TargetRelocationHa
>    case R_X86_64_IRELATIVE:
>    case R_X86_64_JUMP_SLOT:
>    case R_X86_64_GLOB_DAT:
> +  case R_X86_64_DTPMOD64:
> +  case R_X86_64_DTPOFF64:
>      break;
>    default: {
>      std::string str;
> 
> Modified: lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp?rev=218633&r1=218632&r2=218633&view=diff
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp Mon Sep 29 17:05:26 2014
> @@ -50,6 +50,12 @@ const uint8_t x86_64PltAtomContent[16] =
>    0xe9, 0x00, 0x00, 0x00, 0x00        // jmpq plt[-1]
>  };
>  
> +// TLS GD Entry
> +static const uint8_t x86_64GotTlsGdAtomContent[] = {
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +};
> +
>  /// \brief Atoms that are used by X86_64 dynamic linking
>  class X86_64GOTAtom : public GOTAtom {
>  public:
> @@ -60,6 +66,16 @@ public:
>    }
>  };
>  
> +/// \brief X86_64 GOT TLS GD entry.
> +class GOTTLSGdAtom : public X86_64GOTAtom {
> +public:
> +  GOTTLSGdAtom(const File &f, StringRef secName) : X86_64GOTAtom(f, secName) {}
> +
> +  ArrayRef<uint8_t> rawContent() const override {
> +    return llvm::makeArrayRef(x86_64GotTlsGdAtomContent);
> +  }
> +};
> +
>  class X86_64PLT0Atom : public PLT0Atom {
>  public:
>    X86_64PLT0Atom(const File &f) : PLT0Atom(f) {
> @@ -117,6 +133,9 @@ template <class Derived> class Relocatio
>      case R_X86_64_GOTTPOFF: // GOT Thread Pointer Offset
>        static_cast<Derived *>(this)->handleGOTTPOFF(ref);
>        break;
> +    case R_X86_64_TLSGD:
> +      static_cast<Derived *>(this)->handleTLSGd(ref);
> +      break;
>      }
>    }
>  
> @@ -180,6 +199,11 @@ protected:
>      const_cast<Reference &>(ref).setKindValue(R_X86_64_PC32);
>    }
>  
> +  /// \brief Create a TLS GOT entry with DTPMOD64/DTPOFF64 dynamic relocations.
> +  void handleTLSGd(const Reference &ref) {
> +    const_cast<Reference &>(ref).setTarget(getTLSGdGOTEntry(ref.target()));
> +  }
> +
>    /// \brief Create a GOT entry containing 0.
>    const GOTAtom *getNullGOT() {
>      if (!_null) {
> @@ -207,6 +231,21 @@ protected:
>      return got->second;
>    }
>  
> +  const GOTAtom *getTLSGdGOTEntry(const Atom *a) {
> +    auto got = _gotTLSGdMap.find(a);
> +    if (got != _gotTLSGdMap.end())
> +      return got->second;
> +
> +    auto ga = new (_file._alloc) GOTTLSGdAtom(_file, ".got");
> +    _gotTLSGdMap[a] = ga;
> +
> +    _tlsGotVector.push_back(ga);
> +    ga->addReferenceELF_x86_64(R_X86_64_DTPMOD64, 0, a, 0);
> +    ga->addReferenceELF_x86_64(R_X86_64_DTPOFF64, 8, a, 0);
> +
> +    return ga;
> +  }
> +
>  public:
>    RelocationPass(const ELFLinkingContext &ctx)
>        : _file(ctx), _ctx(ctx), _null(nullptr), _PLT0(nullptr), _got0(nullptr),
> @@ -251,6 +290,10 @@ public:
>        got->setOrdinal(ordinal++);
>        mf->addAtom(*got);
>      }
> +    for (auto &got : _tlsGotVector) {
> +      got->setOrdinal(ordinal++);
> +      mf->addAtom(*got);
> +    }
>      for (auto obj : _objectVector) {
>        obj->setOrdinal(ordinal++);
>        mf->addAtom(*obj);
> @@ -268,6 +311,9 @@ protected:
>    /// \brief Map Atoms to their PLT entries.
>    llvm::DenseMap<const Atom *, PLTAtom *> _pltMap;
>  
> +  /// \brief Map Atoms to TLS GD GOT entries.
> +  llvm::DenseMap<const Atom *, GOTAtom *> _gotTLSGdMap;
> +
>    /// \brief Map Atoms to their Object entries.
>    llvm::DenseMap<const Atom *, ObjectAtom *> _objectMap;
>  
> @@ -276,6 +322,9 @@ protected:
>    std::vector<PLTAtom *> _pltVector;
>    std::vector<ObjectAtom *> _objectVector;
>  
> +  /// \brief the list of TLS GOT atoms.
> +  std::vector<GOTAtom *> _tlsGotVector;
> +
>    /// \brief GOT entry that is always 0. Used for undefined weaks.
>    GOTAtom *_null;
>  
> @@ -414,7 +463,10 @@ public:
>              dyn_cast_or_null<const DefinedAtom>(ref.target()))
>        if (da->contentType() == DefinedAtom::typeResolver)
>          return handleIFUNC(ref);
> -    if (isa<const SharedLibraryAtom>(ref.target()))
> +    // If it is undefined at link time, push the work to the dynamic linker by
> +    // creating a PLT entry
> +    if (isa<SharedLibraryAtom>(ref.target()) ||
> +        isa<UndefinedAtom>(ref.target()))
>        const_cast<Reference &>(ref).setTarget(getPLTEntry(ref.target()));
>      return std::error_code();
>    }
> 
> Added: lld/trunk/test/elf/X86_64/Inputs/generaltls-so.o.yaml
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/Inputs/generaltls-so.o.yaml?rev=218633&view=auto
> ==============================================================================
> --- lld/trunk/test/elf/X86_64/Inputs/generaltls-so.o.yaml (added)
> +++ lld/trunk/test/elf/X86_64/Inputs/generaltls-so.o.yaml Mon Sep 29 17:05:26 2014
> @@ -0,0 +1,68 @@
> +---
> +FileHeader:
> +  Class:           ELFCLASS64
> +  Data:            ELFDATA2LSB
> +  OSABI:           ELFOSABI_GNU
> +  Type:            ET_REL
> +  Machine:         EM_X86_64
> +Sections:
> +  - Name:            .text
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
> +    AddressAlign:    0x0000000000000010
> +    Content:         554889E566488D3D00000000666648E8000000008B005DC3
> +  - Name:            .rela.text
> +    Type:            SHT_RELA
> +    Link:            .symtab
> +    AddressAlign:    0x0000000000000008
> +    Info:            .text
> +    Relocations:
> +      - Offset:          0x0000000000000008
> +        Symbol:          mynumber
> +        Type:            R_X86_64_TLSGD
> +        Addend:          -4
> +      - Offset:          0x0000000000000010
> +        Symbol:          __tls_get_addr
> +        Type:            R_X86_64_PLT32
> +        Addend:          -4
> +  - 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:            .tdata
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
> +    AddressAlign:    0x0000000000000004
> +    Content:         '21000000'
> +Symbols:
> +  Local:
> +    - Name:            .text
> +      Type:            STT_SECTION
> +      Section:         .text
> +    - Name:            .data
> +      Type:            STT_SECTION
> +      Section:         .data
> +    - Name:            .bss
> +      Type:            STT_SECTION
> +      Section:         .bss
> +    - Name:            .tdata
> +      Type:            STT_SECTION
> +      Section:         .tdata
> +  Global:
> +    - Name:            getnumber
> +      Type:            STT_FUNC
> +      Section:         .text
> +      Size:            0x0000000000000018
> +    - Name:            mynumber
> +      Type:            STT_TLS
> +      Section:         .tdata
> +      Size:            0x0000000000000004
> +    - Name:            _GLOBAL_OFFSET_TABLE_
> +    - Name:            __tls_get_addr
> +...
> 
> Added: lld/trunk/test/elf/X86_64/general-dynamic-tls.test
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/general-dynamic-tls.test?rev=218633&view=auto
> ==============================================================================
> --- lld/trunk/test/elf/X86_64/general-dynamic-tls.test (added)
> +++ lld/trunk/test/elf/X86_64/general-dynamic-tls.test Mon Sep 29 17:05:26 2014
> @@ -0,0 +1,129 @@
> +# This test exercises a simple general dynamic TLS access model in X86_64.
> +#
> +# It is composed of two parts: a program and a shared library. The shared
> +# library uses TLS, but the program does not.
> +#
> +# The shared library should import __tls_get_addr, since it uses the general
> +# dynamic TLS access mode (see www.akkadia.org/drepper/tls.pdf). Notice that
> +# once we support TLS strength reduction, this test should be updated, since
> +# this can be converted into a local dynamic TLS model.
> +
> +# Prepare inputs
> +#RUN: yaml2obj -format=elf %p/Inputs/generaltls-so.o.yaml -o=%t.o.so
> +#RUN: lld -flavor gnu  -target x86_64 -shared %t.o.so -o %T/libgeneraltls.so
> +#RUN: yaml2obj -format=elf %s -o=%t.o
> +
> +# Link - (we supply --defsym=__tls_get_addr to avoid the need to link with
> +# system libraries)
> +#RUN: lld -flavor gnu  -target x86_64 -e main %t.o -L%T -lgeneraltls -o %t1 \
> +#RUN:   --defsym=__tls_get_addr=0
> +
> +# Check
> +#RUN: llvm-readobj -dyn-symbols %t1 | FileCheck -check-prefix CHECKPROG %s
> +#RUN: llvm-readobj -relocations -dyn-symbols %T/libgeneraltls.so | FileCheck \
> +#RUN:     -check-prefix CHECKDSO %s
> +
> +# Test case generated with the following code:
> +#
> +# DSO: (file %p/Inputs/generaltls-so.o.yaml)
> +#
> +# __thread int mynumber=33;
> +#
> +# int getnumber() {
> +#     return mynumber;
> +# }
> +#
> +# Program: (this file). Note: The printf() relocation was removed to simplify
> +# this test and allow us to test this without libc.
> +#
> +# #include <stdio.h>
> +# int getnumber();
> +#
> +# int main() {
> +#     printf("getnumber() = %d\n", getnumber());
> +#     return 0;
> +# }
> +#
> +---
> +FileHeader:
> +  Class:           ELFCLASS64
> +  Data:            ELFDATA2LSB
> +  OSABI:           ELFOSABI_GNU
> +  Type:            ET_REL
> +  Machine:         EM_X86_64
> +Sections:
> +  - Name:            .text
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
> +    AddressAlign:    0x0000000000000010
> +    Content:         554889E54883EC10C745FC00000000B000E80000000048BF000000000000000089C6B000E80000000031F68945F889F04883C4105DC3
> +  - Name:            .rela.text
> +    Type:            SHT_RELA
> +    Link:            .symtab
> +    AddressAlign:    0x0000000000000008
> +    Info:            .text
> +    Relocations:
> +      - Offset:          0x0000000000000012
> +        Symbol:          getnumber
> +        Type:            R_X86_64_PC32
> +        Addend:          -4
> +      - Offset:          0x0000000000000018
> +        Symbol:          .rodata.str1.1
> +        Type:            R_X86_64_64
> +        Addend:          0
> +  - 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:            .rodata.str1.1
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_ALLOC, SHF_MERGE, SHF_STRINGS ]
> +    AddressAlign:    0x0000000000000001
> +    Content:         6765746E756D6265722829203D2025640A00
> +Symbols:
> +  Local:
> +    - Name:            .text
> +      Type:            STT_SECTION
> +      Section:         .text
> +    - Name:            .data
> +      Type:            STT_SECTION
> +      Section:         .data
> +    - Name:            .bss
> +      Type:            STT_SECTION
> +      Section:         .bss
> +    - Name:            .rodata.str1.1
> +      Type:            STT_SECTION
> +      Section:         .rodata.str1.1
> +  Global:
> +    - Name:            main
> +      Type:            STT_FUNC
> +      Section:         .text
> +      Size:            0x0000000000000036
> +    - Name:            getnumber
> +
> +# Program should import the function defined in the shared library
> +#CHECKPROG: getnumber@
> +# Program should not import __tls_get_addr, since it does not directly use TLS
> +#CHECKPROG-NOT: __tls_get_addr@
> +
> +# Check for the presence of X86_64 TLS relocations in the shared library
> +#CHECKDSO: R_X86_64_DTPMOD64
> +#CHECKDSO: R_X86_64_DTPOFF64
> +#CHECKDSO: R_X86_64_JUMP_SLOT
> +
> +# The shared library should import __tls_get_addr, since it uses the general
> +# dynamic TLS access mode.
> +#CHECKDSO:          Name: __tls_get_addr@
> +#CHECKDSO-NEXT:     Value: 0x0
> +#CHECKDSO-NEXT:     Size: 0
> +#CHECKDSO-NEXT:     Binding: Global
> +#CHECKDSO-NEXT:     Type: None
> +#CHECKDSO-NEXT:     Other: 0
> +#CHECKDSO-NEXT:     Section: Undefined
> +
> 
> Modified: lld/trunk/test/elf/X86_64/omagic.test
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/omagic.test?rev=218633&r1=218632&r2=218633&view=diff
> ==============================================================================
> --- lld/trunk/test/elf/X86_64/omagic.test (original)
> +++ lld/trunk/test/elf/X86_64/omagic.test Mon Sep 29 17:05:26 2014
> @@ -185,7 +185,7 @@ OMAGICSECTIONS:    Flags [ (0x0)
>  OMAGICSECTIONS:    ]
>  OMAGICSECTIONS:    Address: 0x0
>  OMAGICSECTIONS:    Offset: 0x1E8
> -OMAGICSECTIONS:    Size: 528
> +OMAGICSECTIONS:    Size: 504
>  OMAGICSECTIONS:    Link: 13
>  OMAGICSECTIONS:    Info: 2
>  OMAGICSECTIONS:    AddressAlignment: 8
> @@ -197,8 +197,8 @@ OMAGICSECTIONS:    Type: SHT_STRTAB (0x3
>  OMAGICSECTIONS:    Flags [ (0x0)
>  OMAGICSECTIONS:    ]
>  OMAGICSECTIONS:    Address: 0x0
> -OMAGICSECTIONS:    Offset: 0x3F8
> -OMAGICSECTIONS:    Size: 246
> +OMAGICSECTIONS:    Offset: 0x3E0
> +OMAGICSECTIONS:    Size: 231
>  OMAGICSECTIONS:    Link: 0
>  OMAGICSECTIONS:    Info: 0
>  OMAGICSECTIONS:    AddressAlignment: 1
> 
> Modified: lld/trunk/test/elf/X86_64/undef.test
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/undef.test?rev=218633&r1=218632&r2=218633&view=diff
> ==============================================================================
> --- lld/trunk/test/elf/X86_64/undef.test (original)
> +++ lld/trunk/test/elf/X86_64/undef.test Mon Sep 29 17:05:26 2014
> @@ -7,7 +7,7 @@ RUN: lld -flavor gnu -target x86_64 %p/I
>  RUN: llvm-readobj -symbols %t | FileCheck %s
>  
>  SYMFROMARCHIVE:  Symbol {
> -SYMFROMARCHIVE:    Name: fn (16)
> +SYMFROMARCHIVE:    Name: fn ({{[0-9]+}}
>  SYMFROMARCHIVE:    Size: 11
>  SYMFROMARCHIVE:    Binding: Global (0x1)
>  SYMFROMARCHIVE:    Type: Function (0x2)
> 
> Modified: lld/trunk/test/elf/X86_64/underscore-end.test
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/underscore-end.test?rev=218633&r1=218632&r2=218633&view=diff
> ==============================================================================
> --- lld/trunk/test/elf/X86_64/underscore-end.test (original)
> +++ lld/trunk/test/elf/X86_64/underscore-end.test Mon Sep 29 17:05:26 2014
> @@ -7,7 +7,7 @@ RUN: --noinhibit-exec -o %t --omagic
>  RUN: llvm-readobj -symbols %t | FileCheck -check-prefix=OMAGICABSSYMBOLS %s
>  
>  NMAGICABSSYMBOLS:  Symbol {
> -NMAGICABSSYMBOLS:    Name: __bss_start (51)
> +NMAGICABSSYMBOLS:    Name: __bss_start ({{[0-9]+}}
>  NMAGICABSSYMBOLS:    Value: 0x40100C
>  NMAGICABSSYMBOLS:    Size: 0
>  NMAGICABSSYMBOLS:    Binding: Global (0x1)
> @@ -16,7 +16,7 @@ NMAGICABSSYMBOLS:    Other: 0
>  NMAGICABSSYMBOLS:    Section: Absolute (0xFFF1)
>  NMAGICABSSYMBOLS:  }
>  NMAGICABSSYMBOLS:  Symbol {
> -NMAGICABSSYMBOLS:    Name: __bss_end (63)
> +NMAGICABSSYMBOLS:    Name: __bss_end ({{[0-9]+}}
>  NMAGICABSSYMBOLS:    Value: 0x40100C
>  NMAGICABSSYMBOLS:    Size: 0
>  NMAGICABSSYMBOLS:    Binding: Global (0x1)
> @@ -25,7 +25,7 @@ NMAGICABSSYMBOLS:    Other: 0
>  NMAGICABSSYMBOLS:    Section: Absolute (0xFFF1)
>  NMAGICABSSYMBOLS:  }
>  NMAGICABSSYMBOLS:  Symbol {
> -NMAGICABSSYMBOLS:    Name: _end (73)
> +NMAGICABSSYMBOLS:    Name: _end ({{[0-9]+}}
>  NMAGICABSSYMBOLS:    Value: 0x40100C
>  NMAGICABSSYMBOLS:    Size: 0
>  NMAGICABSSYMBOLS:    Binding: Global (0x1)
> @@ -34,7 +34,7 @@ NMAGICABSSYMBOLS:    Other: 0
>  NMAGICABSSYMBOLS:    Section: Absolute (0xFFF1)
>  NMAGICABSSYMBOLS:  }
>  NMAGICABSSYMBOLS:  Symbol {
> -NMAGICABSSYMBOLS:    Name: end (78)
> +NMAGICABSSYMBOLS:    Name: end ({{[0-9]+}}
>  NMAGICABSSYMBOLS:    Value: 0x40100C
>  NMAGICABSSYMBOLS:    Size: 0
>  NMAGICABSSYMBOLS:    Binding: Global (0x1)
> @@ -44,7 +44,7 @@ NMAGICABSSYMBOLS:    Section: Absolute (
>  NMAGICABSSYMBOLS:  }
>  
>  OMAGICABSSYMBOLS:  Symbol {
> -OMAGICABSSYMBOLS:    Name: __bss_start (51)
> +OMAGICABSSYMBOLS:    Name: __bss_start ({{[0-9]+}})
>  OMAGICABSSYMBOLS:    Value: 0x400144
>  OMAGICABSSYMBOLS:    Size: 0
>  OMAGICABSSYMBOLS:    Binding: Global (0x1)
> @@ -53,7 +53,7 @@ OMAGICABSSYMBOLS:    Other: 0
>  OMAGICABSSYMBOLS:    Section: Absolute (0xFFF1)
>  OMAGICABSSYMBOLS:  }
>  OMAGICABSSYMBOLS:  Symbol {
> -OMAGICABSSYMBOLS:    Name: __bss_end (63)
> +OMAGICABSSYMBOLS:    Name: __bss_end ({{[0-9]+}}
>  OMAGICABSSYMBOLS:    Value: 0x400144
>  OMAGICABSSYMBOLS:    Size: 0
>  OMAGICABSSYMBOLS:    Binding: Global (0x1)
> @@ -62,7 +62,7 @@ OMAGICABSSYMBOLS:    Other: 0
>  OMAGICABSSYMBOLS:    Section: Absolute (0xFFF1)
>  OMAGICABSSYMBOLS:  }
>  OMAGICABSSYMBOLS:  Symbol {
> -OMAGICABSSYMBOLS:    Name: _end (73)
> +OMAGICABSSYMBOLS:    Name: _end ({{[0-9]+}}
>  OMAGICABSSYMBOLS:    Value: 0x400144
>  OMAGICABSSYMBOLS:    Size: 0
>  OMAGICABSSYMBOLS:    Binding: Global (0x1)
> @@ -71,7 +71,7 @@ OMAGICABSSYMBOLS:    Other: 0
>  OMAGICABSSYMBOLS:    Section: Absolute (0xFFF1)
>  OMAGICABSSYMBOLS:  }
>  OMAGICABSSYMBOLS:  Symbol {
> -OMAGICABSSYMBOLS:    Name: end (78)
> +OMAGICABSSYMBOLS:    Name: end ({{[0-9]+}}
>  OMAGICABSSYMBOLS:    Value: 0x400144
>  OMAGICABSSYMBOLS:    Size: 0
>  OMAGICABSSYMBOLS:    Binding: Global (0x1)
> 
> Modified: lld/trunk/test/elf/dynamic-segorder.test
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/dynamic-segorder.test?rev=218633&r1=218632&r2=218633&view=diff
> ==============================================================================
> --- lld/trunk/test/elf/dynamic-segorder.test (original)
> +++ lld/trunk/test/elf/dynamic-segorder.test Mon Sep 29 17:05:26 2014
> @@ -1,5 +1,6 @@
>  RUN: lld -flavor gnu -target x86_64-linux %p/Inputs/tls.x86-64 \
> -RUN:   %p/Inputs/shared.so-x86-64 -o %t -e main --allow-shlib-undefined
> +RUN:   %p/Inputs/shared.so-x86-64 -o %t -e main --allow-shlib-undefined \
> +RUN:   --defsym=__tls_get_addr=0
>  RUN: llvm-objdump -p %t | FileCheck %s
>  
>  CHECK: PHDR
> 
> Modified: lld/trunk/test/elf/dynamic-undef.test
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/dynamic-undef.test?rev=218633&r1=218632&r2=218633&view=diff
> ==============================================================================
> --- lld/trunk/test/elf/dynamic-undef.test (original)
> +++ lld/trunk/test/elf/dynamic-undef.test Mon Sep 29 17:05:26 2014
> @@ -9,7 +9,8 @@ RUN:   %p/Inputs/shared.so-x86-64 -o %t
>  RUN: FileCheck -check-prefix=EXEC %s < %t1
>  # This test will pass because of --allow-shlib-undefined
>  RUN: lld -flavor gnu -target x86_64-linux %p/Inputs/tls.x86-64 \
> -RUN:   %p/Inputs/shared.so-x86-64 -o %t -e main --allow-shlib-undefined
> +RUN:   %p/Inputs/shared.so-x86-64 -o %t -e main --allow-shlib-undefined \
> +RUN:   --defsym=__tls_get_addr=0
>  # Building shared libraries should not fail when there is a undefined symbol.
>  # Test creation of shared library, this should pass because we are using
>  # shared option and by default, dynamic library wouldn't create undefined atoms
> 
> Modified: lld/trunk/test/elf/undef-from-main-dso.test
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/undef-from-main-dso.test?rev=218633&r1=218632&r2=218633&view=diff
> ==============================================================================
> --- lld/trunk/test/elf/undef-from-main-dso.test (original)
> +++ lld/trunk/test/elf/undef-from-main-dso.test Mon Sep 29 17:05:26 2014
> @@ -41,4 +41,3 @@ CHECK-NEXT:    Type: Object (0x1)
>  CHECK-NEXT:    Other: 0
>  CHECK-NEXT:    Section: .bss
>  
> -CHECK:         Name: x@ ({{[0-9]+}}
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits



More information about the llvm-commits mailing list