[lld] r232708 - [ARM] Implement static (initial exec) TLS model

Denis Protivensky dprotivensky at accesssoftek.com
Wed Mar 18 23:47:45 PDT 2015


Author: denis-protivensky
Date: Thu Mar 19 01:47:44 2015
New Revision: 232708

URL: http://llvm.org/viewvc/llvm-project?rev=232708&view=rev
Log:
[ARM] Implement static (initial exec) TLS model

This includes handling of R_ARM_TLS_IE32 and R_ARM_TLS_LE32 relocs.

Differential Revision: http://reviews.llvm.org/D8353

Added:
    lld/trunk/test/elf/ARM/rel-tls-ie32.test
    lld/trunk/test/elf/ARM/rel-tls-le32.test
Modified:
    lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp
    lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.h
    lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp
    lld/trunk/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.cpp
    lld/trunk/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h

Modified: lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp?rev=232708&r1=232707&r2=232708&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp Thu Mar 19 01:47:44 2015
@@ -82,6 +82,8 @@ static Reference::Addend readAddend(cons
   switch (kindValue) {
   case R_ARM_ABS32:
   case R_ARM_REL32:
+  case R_ARM_TLS_IE32:
+  case R_ARM_TLS_LE32:
     return (int32_t)read32le(location);
   case R_ARM_PREL31:
     return (int32_t)(read32le(location) & 0x7FFFFFFF);
@@ -382,6 +384,34 @@ static void relocR_ARM_THM_MOVT_ABS(uint
   return relocR_ARM_THM_MOV(location, arg);
 }
 
+/// \brief R_ARM_TLS_IE32 - GOT(S) + A - P => S + A - P
+static void relocR_ARM_TLS_IE32(uint8_t *location, uint64_t P, uint64_t S,
+                                int64_t A) {
+  uint32_t result = (uint32_t)(S + A - P);
+
+  DEBUG_WITH_TYPE(
+      "ARM", llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
+      llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
+      llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
+      llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
+      llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
+  applyArmReloc(location, result);
+}
+
+/// \brief R_ARM_TLS_LE32 - S + A - tp => S + A + tpoff
+static void relocR_ARM_TLS_LE32(uint8_t *location, uint64_t P, uint64_t S,
+                                int64_t A, uint64_t tpoff) {
+  uint32_t result = (uint32_t)(S + A + tpoff);
+
+  DEBUG_WITH_TYPE(
+      "ARM", llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -";
+      llvm::dbgs() << " S: 0x" << Twine::utohexstr(S);
+      llvm::dbgs() << " A: 0x" << Twine::utohexstr(A);
+      llvm::dbgs() << " P: 0x" << Twine::utohexstr(P);
+      llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
+  applyArmReloc(location, result);
+}
+
 std::error_code ARMTargetRelocationHandler::applyRelocation(
     ELFWriter &writer, llvm::FileOutputBuffer &buf, const lld::AtomLayout &atom,
     const Reference &ref) const {
@@ -455,6 +485,13 @@ std::error_code ARMTargetRelocationHandl
     relocR_ARM_PREL31(location, relocVAddress, targetVAddress, addend,
                      addressesThumb);
     break;
+  case R_ARM_TLS_IE32:
+    relocR_ARM_TLS_IE32(location, relocVAddress, targetVAddress, addend);
+    break;
+  case R_ARM_TLS_LE32:
+    relocR_ARM_TLS_LE32(location, relocVAddress, targetVAddress, addend,
+                        _armLayout.getTPOffset());
+    break;
   default:
     return make_unhandled_reloc_error();
   }

Modified: lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.h?rev=232708&r1=232707&r2=232708&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.h Thu Mar 19 01:47:44 2015
@@ -21,9 +21,15 @@ template <class ELFT> class ARMTargetLay
 class ARMTargetRelocationHandler final
     : public TargetRelocationHandler {
 public:
+  ARMTargetRelocationHandler(ARMTargetLayout<ARMELFType> &layout)
+      : _armLayout(layout) {}
+
   std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
                                   const lld::AtomLayout &,
                                   const Reference &) const override;
+
+private:
+  ARMTargetLayout<ARMELFType> &_armLayout;
 };
 
 } // end namespace elf

Modified: lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp?rev=232708&r1=232707&r2=232708&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp Thu Mar 19 01:47:44 2015
@@ -28,11 +28,10 @@ using namespace lld;
 using namespace lld::elf;
 using namespace llvm::ELF;
 
-namespace {
 // ARM B/BL instructions of static relocation veneer.
 // TODO: consider different instruction set for archs below ARMv5
 // (one as for Thumb may be used though it's less optimal).
-const uint8_t Veneer_ARM_B_BL_StaticAtomContent[8] = {
+static const uint8_t Veneer_ARM_B_BL_StaticAtomContent[8] = {
     0x04, 0xf0, 0x1f, 0xe5,  // ldr pc, [pc, #-4]
     0x00, 0x00, 0x00, 0x00   // <target_symbol_address>
 };
@@ -40,12 +39,16 @@ const uint8_t Veneer_ARM_B_BL_StaticAtom
 // Thumb B/BL instructions of static relocation veneer.
 // TODO: consider different instruction set for archs above ARMv5
 // (one as for ARM may be used since it's more optimal).
-const uint8_t Veneer_THM_B_BL_StaticAtomContent[8] = {
+static const uint8_t Veneer_THM_B_BL_StaticAtomContent[8] = {
     0x78, 0x47,              // bx pc
     0x00, 0x00,              // nop
     0xfe, 0xff, 0xff, 0xea   // b <target_symbol_address>
 };
 
+// .got values
+static const uint8_t ARMGotAtomContent[4] = {0};
+
+namespace {
 /// \brief Atoms that hold veneer code.
 class VeneerAtom : public SimpleELFDefinedAtom {
   StringRef _section;
@@ -104,6 +107,18 @@ public:
   }
 };
 
+/// \brief Atoms that are used by ARM dynamic linking
+class ARMGOTAtom : public GOTAtom {
+public:
+  ARMGOTAtom(const File &f, StringRef secName) : GOTAtom(f, secName) {}
+
+  ArrayRef<uint8_t> rawContent() const override {
+    return llvm::makeArrayRef(ARMGotAtomContent);
+  }
+
+  Alignment alignment() const override { return Alignment(2); }
+};
+
 class ELFPassFile : public SimpleFile {
 public:
   ELFPassFile(const ELFLinkingContext &eti) : SimpleFile("ELFPassFile") {
@@ -129,6 +144,9 @@ template <class Derived> class ARMReloca
     case R_ARM_THM_JUMP24:
       static_cast<Derived *>(this)->handleVeneer(atom, ref);
       break;
+    case R_ARM_TLS_IE32:
+      static_cast<Derived *>(this)->handleTLSIE32(ref);
+      break;
     }
   }
 
@@ -136,7 +154,7 @@ protected:
   std::error_code handleVeneer(const DefinedAtom &atom, const Reference &ref) {
     // Target symbol and relocated place should have different
     // instruction sets in order a veneer to be generated in between.
-    const auto *target = dyn_cast_or_null<DefinedAtom>(ref.target());
+    const auto *target = dyn_cast<DefinedAtom>(ref.target());
     if (!target || target->codeModel() == atom.codeModel())
       return std::error_code();
 
@@ -183,6 +201,32 @@ protected:
     return std::error_code();
   }
 
+  std::error_code handleTLSIE32(const Reference &ref) {
+    if (const auto *target = dyn_cast<DefinedAtom>(ref.target())) {
+      const_cast<Reference &>(ref).setTarget(
+          static_cast<Derived *>(this)->getTLSTPOFF32(target));
+      return std::error_code();
+    }
+    llvm_unreachable("R_ARM_TLS_IE32 reloc targets wrong atom type");
+  }
+
+  /// \brief Create a GOT entry for TLS with reloc type and addend specified.
+  template <Reference::KindValue R_ARM_TLS, Reference::Addend A = 0>
+  const GOTAtom *getGOTTLSEntry(const DefinedAtom *da) {
+    auto got = _gotMap.find(da);
+    if (got != _gotMap.end())
+      return got->second;
+    auto g = new (_file._alloc) ARMGOTAtom(_file, ".got");
+    g->addReferenceELF_ARM(R_ARM_TLS, 0, da, A);
+#ifndef NDEBUG
+    g->_name = "__got_tls_";
+    g->_name += da->name();
+#endif
+    _gotMap[da] = g;
+    _gotVector.push_back(g);
+    return g;
+  }
+
 public:
   ARMRelocationPass(const ELFLinkingContext &ctx) : _file(ctx), _ctx(ctx) {}
 
@@ -230,6 +274,10 @@ public:
 
     // Add all created atoms to the link.
     uint64_t ordinal = 0;
+    for (auto &got : _gotVector) {
+      got->setOrdinal(ordinal++);
+      mf->addAtom(*got);
+    }
     for (auto &veneer : _veneerVector) {
       veneer->setOrdinal(ordinal++);
       mf->addAtom(*veneer);
@@ -241,9 +289,15 @@ protected:
   ELFPassFile _file;
   const ELFLinkingContext &_ctx;
 
+  /// \brief Map Atoms to their GOT entries.
+  llvm::DenseMap<const Atom *, GOTAtom *> _gotMap;
+
   /// \brief Map Atoms to their veneers.
   llvm::DenseMap<const Atom *, VeneerAtom *> _veneerMap;
 
+  /// \brief the list of GOT/PLT atoms
+  std::vector<GOTAtom *> _gotVector;
+
   /// \brief the list of veneer atoms.
   std::vector<VeneerAtom *> _veneerVector;
 };
@@ -297,6 +351,11 @@ public:
     _veneerVector.push_back(v);
     return v;
   }
+
+  /// \brief Create a GOT entry for R_ARM_TLS_TPOFF32 reloc.
+  const GOTAtom *getTLSTPOFF32(const DefinedAtom *da) {
+    return getGOTTLSEntry<R_ARM_TLS_LE32>(da);
+  }
 };
 
 } // end of anon namespace

Modified: lld/trunk/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.cpp?rev=232708&r1=232707&r2=232708&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.cpp Thu Mar 19 01:47:44 2015
@@ -18,7 +18,8 @@ using namespace elf;
 ARMTargetHandler::ARMTargetHandler(ARMLinkingContext &context)
     : _context(context), _armTargetLayout(
           new ARMTargetLayout<ARMELFType>(context)),
-      _armRelocationHandler(new ARMTargetRelocationHandler()) {}
+      _armRelocationHandler(new ARMTargetRelocationHandler(
+          *_armTargetLayout.get())) {}
 
 void ARMTargetHandler::registerRelocationNames(Registry &registry) {
   registry.addKindTable(Reference::KindNamespace::ELF, Reference::KindArch::ARM,

Modified: lld/trunk/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h?rev=232708&r1=232707&r2=232708&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h Thu Mar 19 01:47:44 2015
@@ -29,6 +29,26 @@ template <class ELFT> class ARMTargetLay
 public:
   ARMTargetLayout(ARMLinkingContext &context)
       : TargetLayout<ELFT>(context) {}
+
+  uint64_t getTPOffset() {
+    if (_tpOff.hasValue())
+      return *_tpOff;
+
+    for (const auto &phdr : *this->_programHeader) {
+      if (phdr->p_type == llvm::ELF::PT_TLS) {
+        _tpOff = llvm::RoundUpToAlignment(TCB_SIZE, phdr->p_align);
+        return *_tpOff;
+      }
+    }
+    llvm_unreachable("TLS segment not found");
+  }
+
+private:
+  // TCB block size of the TLS.
+  enum { TCB_SIZE = 0x8 };
+
+  // Cached value of the TLS offset from the $tp pointer.
+  llvm::Optional<uint64_t> _tpOff;
 };
 
 class ARMTargetHandler final : public DefaultTargetHandler<ARMELFType> {

Added: lld/trunk/test/elf/ARM/rel-tls-ie32.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/ARM/rel-tls-ie32.test?rev=232708&view=auto
==============================================================================
--- lld/trunk/test/elf/ARM/rel-tls-ie32.test (added)
+++ lld/trunk/test/elf/ARM/rel-tls-ie32.test Thu Mar 19 01:47:44 2015
@@ -0,0 +1,109 @@
+# Check handling of R_ARM_TLS_IE32 relocation.
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-tls.o
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t-tlsv.o
+# RUN: lld -flavor gnu -target arm -m armelf_linux_eabi -Bstatic \
+# RUN: --noinhibit-exec %t-tls.o %t-tlsv.o -o %t
+# RUN: llvm-objdump -s -t %t | FileCheck %s
+
+# CHECK: Contents of section .got:
+# CHECK: 401008 08000000 0c000000
+#  tp_off(i) = 0x08 ^^     ^^ tp_off(j) = 0x0c
+#               tp_off(i) + sizeof(i) =  tp_off(j)
+#                 0x08    +   0x04    =    0x0c
+# CHECK: SYMBOL TABLE:
+# CHECK: 00400094 g     F .text  {{[0-9a-f]+}} main
+# CHECK: 00000000 g       .tdata 00000004 i
+#                  sizeof(i) = 0x04 ^^
+# CHECK: 00000004 g       .tdata 00000004 j
+
+# tls.o
+---
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_ARM
+  Flags:           [ EF_ARM_EABI_VER5 ]
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x0000000000000004
+    Content:         80B400AF0C4B7B441B681DEE702FD2580A4B7B441B681DEE701FCB581A44084B7B441B681DEE701FCB585B0013441846BD465DF8047B70472E000000260000001C000000
+  - Name:            .rel.text
+    Type:            SHT_REL
+    Link:            .symtab
+    AddressAlign:    0x0000000000000004
+    Info:            .text
+    Relocations:
+      - Offset:          0x0000000000000038
+        Symbol:          i
+        Type:            R_ARM_TLS_IE32
+      - Offset:          0x000000000000003C
+        Symbol:          i
+        Type:            R_ARM_TLS_IE32
+      - Offset:          0x0000000000000040
+        Symbol:          j
+        Type:            R_ARM_TLS_IE32
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+    Content:         ''
+  - Name:            .bss
+    Type:            SHT_NOBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+    Content:         ''
+Symbols:
+  Global:
+    - Name:            main
+      Type:            STT_FUNC
+      Section:         .text
+      Value:           0x0000000000000001
+    - Name:            i
+      Type:            STT_TLS
+    - Name:            j
+      Type:            STT_TLS
+
+# tlsv.o
+---
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_ARM
+  Flags:           [ EF_ARM_EABI_VER5 ]
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x0000000000000001
+    Content:         ''
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+    Content:         ''
+  - Name:            .bss
+    Type:            SHT_NOBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+    Content:         ''
+  - Name:            .tdata
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
+    AddressAlign:    0x0000000000000004
+    Content:         05000000FBFFFFFF
+Symbols:
+  Global:
+    - Name:            i
+      Type:            STT_TLS
+      Section:         .tdata
+      Size:            0x0000000000000004
+    - Name:            j
+      Type:            STT_TLS
+      Section:         .tdata
+      Value:           0x0000000000000004
+      Size:            0x0000000000000004
+...

Added: lld/trunk/test/elf/ARM/rel-tls-le32.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/ARM/rel-tls-le32.test?rev=232708&view=auto
==============================================================================
--- lld/trunk/test/elf/ARM/rel-tls-le32.test (added)
+++ lld/trunk/test/elf/ARM/rel-tls-le32.test Thu Mar 19 01:47:44 2015
@@ -0,0 +1,61 @@
+# Check handling of R_ARM_TLS_LE32 relocation.
+# RUN: yaml2obj -format=elf %s > %t-o.o
+# RUN: lld -flavor gnu -target arm -m armelf_linux_eabi -Bstatic \
+# RUN: --noinhibit-exec %t-o.o -o %t
+# RUN: llvm-objdump -s -t %t | FileCheck %s
+
+# CHECK: Contents of section .text:
+# CHECK: 4000b4 {{[0-9a-f]+}} 08000000
+#              tp_off = 0x000008 ^^
+# CHECK: SYMBOL TABLE:
+# CHECK: 00400094 g     F .text  {{[0-9a-f]+}} main
+# CHECK: 00000000 g       .tdata 00000004 i
+
+---
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_ARM
+  Flags:           [ EF_ARM_EABI_VER5 ]
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x0000000000000004
+    Content:         04B02DE500B08DE2703F1DEE10209FE5023093E70300A0E100D04BE204B09DE41EFF2FE100000000
+  - Name:            .rel.text
+    Type:            SHT_REL
+    Link:            .symtab
+    AddressAlign:    0x0000000000000004
+    Info:            .text
+    Relocations:
+      - Offset:          0x0000000000000024
+        Symbol:          i
+        Type:            R_ARM_TLS_LE32
+        Addend:          0
+  - Name:            .data
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+    Content:         ''
+  - Name:            .bss
+    Type:            SHT_NOBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]
+    AddressAlign:    0x0000000000000001
+    Content:         ''
+  - Name:            .tdata
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
+    AddressAlign:    0x0000000000000004
+    Content:         '05000000'
+Symbols:
+  Global:
+    - Name:            i
+      Type:            STT_TLS
+      Section:         .tdata
+      Size:            0x0000000000000004
+    - Name:            main
+      Type:            STT_FUNC
+      Section:         .text
+...





More information about the llvm-commits mailing list