[lld] r239908 - [ELF/x86_64] Fix initial-exec TLS access

Adhemerval Zanella azanella at linux.vnet.ibm.com
Wed Jun 17 07:00:12 PDT 2015


Author: azanella
Date: Wed Jun 17 09:00:12 2015
New Revision: 239908

URL: http://llvm.org/viewvc/llvm-project?rev=239908&view=rev
Log:
[ELF/x86_64] Fix initial-exec TLS access

Current approach for initial-exec in ELF/x86_64 is to create a GOT entry
and change the relocation to R_X86_64_PC32 to be handled as a GOT offfset.
However there are two issues with this approach: 1. the R_X86_64_PC32 is
not really required since the GOT relocation will be handle dynamically and
2. the TLS symbols are not being exported externally and then correct
realocation are not being applied.

This patch fixes the R_X86_64_GOTTPOFF handling by just emitting a
R_X86_64_TPOFF64 dynamically one; it also sets R_X86_64_TPOFF64 to be
handled by runtime one.  For second part, the patches uses a similar
strategy used for aarch64, by reimplementing buildDynamicSymbolTable
from X86_64ExecutableWriter and adding the TLS symbols in the dynamic
symbol table.

Some tests had to be adjusted due the now missing R_X86_64_PC32 relocation.
With this test the simple testcase:

* t1.c:

__thread int t0;
__thread int t1;
__thread int t2;
__thread int t3;

* t0.c:

extern __thread int t0;
extern __thread int t1;
extern __thread int t2;
extern __thread int t3;

__thread int t4;
__thread int t5;
__thread int t6;
__thread int t7;

int main ()
{
  t0 = 1;
  t1 = 2;
  t2 = 3;
  t3 = 4;

  t4 = 5;
  t5 = 6;
  t6 = 7;
  t7 = 8;

  printf ("%i %i %i %i\n", t0, t1, t2, t3);
  printf ("%i %i %i %i\n", t4, t5, t6, t7);

  return 0;
}

Shows correct output for x86_64.

Added:
    lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp
    lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.h
Modified:
    lld/trunk/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt
    lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h
    lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp
    lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp
    lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h
    lld/trunk/test/elf/X86_64/extern-tls.test
    lld/trunk/test/elf/gottpoff.test
    lld/trunk/test/elf/tls.test

Modified: lld/trunk/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt?rev=239908&r1=239907&r2=239908&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt (original)
+++ lld/trunk/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt Wed Jun 17 09:00:12 2015
@@ -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

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=239908&r1=239907&r2=239908&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h Wed Jun 17 09:00:12 2015
@@ -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

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=239908&r1=239907&r2=239908&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp Wed Jun 17 09:00:12 2015
@@ -94,18 +94,14 @@ std::error_code X86_64TargetRelocationHa
   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_64TargetRelocationHa
   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();

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=239908&r1=239907&r2=239908&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp Wed Jun 17 09:00:12 2015
@@ -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.

Added: lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp?rev=239908&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp (added)
+++ lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp Wed Jun 17 09:00:12 2015
@@ -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

Added: lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.h?rev=239908&view=auto
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.h (added)
+++ lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.h Wed Jun 17 09:00:12 2015
@@ -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

Modified: lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h?rev=239908&r1=239907&r2=239908&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h Wed Jun 17 09:00:12 2015
@@ -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 {

Modified: lld/trunk/test/elf/X86_64/extern-tls.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/X86_64/extern-tls.test?rev=239908&r1=239907&r2=239908&view=diff
==============================================================================
--- lld/trunk/test/elf/X86_64/extern-tls.test (original)
+++ lld/trunk/test/elf/X86_64/extern-tls.test Wed Jun 17 09:00:12 2015
@@ -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

Modified: lld/trunk/test/elf/gottpoff.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/gottpoff.test?rev=239908&r1=239907&r2=239908&view=diff
==============================================================================
--- lld/trunk/test/elf/gottpoff.test (original)
+++ lld/trunk/test/elf/gottpoff.test Wed Jun 17 09:00:12 2015
@@ -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:   }
 
 ---

Modified: lld/trunk/test/elf/tls.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/tls.test?rev=239908&r1=239907&r2=239908&view=diff
==============================================================================
--- lld/trunk/test/elf/tls.test (original)
+++ lld/trunk/test/elf/tls.test Wed Jun 17 09:00:12 2015
@@ -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





More information about the llvm-commits mailing list