[lld] r209582 - [Mips] Handle R_MIPS_TLS_TPREL_HI16 / R_MIPS_TLS_TPREL_LO16 relocations.

Simon Atanasyan simon at atanasyan.com
Sat May 24 09:45:32 PDT 2014


Author: atanasyan
Date: Sat May 24 11:45:31 2014
New Revision: 209582

URL: http://llvm.org/viewvc/llvm-project?rev=209582&view=rev
Log:
[Mips] Handle R_MIPS_TLS_TPREL_HI16 / R_MIPS_TLS_TPREL_LO16 relocations.

Added:
    lld/trunk/test/elf/Mips/tls-1.test
Modified:
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h?rev=209582&r1=209581&r2=209582&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsELFFile.h Sat May 24 11:45:31 2014
@@ -69,7 +69,7 @@ public:
 
   MipsELFFile(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings,
               error_code &ec)
-      : ELFFile<ELFT>(std::move(mb), atomizeStrings, ec), _gp0(0) {}
+      : ELFFile<ELFT>(std::move(mb), atomizeStrings, ec) {}
 
   static ErrorOr<std::unique_ptr<MipsELFFile>>
   create(std::unique_ptr<MemoryBuffer> mb, bool atomizeStrings) {
@@ -101,8 +101,9 @@ public:
     if ((ec = file->createAtoms()))
       return ec;
 
-    // Retrieve registry usage descriptor and GP value.
-    if ((ec = file->readRegInfo()))
+    // Retrieve some auxiliary data like GP value, TLS section address etc
+    // from the object file.
+    if ((ec = file->readAuxData()))
       return ec;
 
     return std::move(file);
@@ -113,7 +114,10 @@ public:
   }
 
   /// \brief gp register value stored in the .reginfo section.
-  int64_t getGP0() const { return _gp0; }
+  int64_t getGP0() const { return *_gp0; }
+
+  /// \brief .tdata section address plus fixed offset.
+  uint64_t getTPOffset() const { return *_tpOff; }
 
 private:
   typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
@@ -121,7 +125,10 @@ private:
   typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
   typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel_Iter Elf_Rel_Iter;
 
-  int64_t _gp0;
+  enum { TP_OFFSET = 0x7000 };
+
+  llvm::Optional<int64_t> _gp0;
+  llvm::Optional<uint64_t> _tpOff;
 
   ErrorOr<ELFDefinedAtom<ELFT> *> handleDefinedSymbol(
       StringRef symName, StringRef sectionName, const Elf_Sym *sym,
@@ -133,24 +140,23 @@ private:
         referenceStart, referenceEnd, referenceList);
   }
 
-  error_code readRegInfo() {
+  error_code readAuxData() {
     typedef llvm::object::Elf_RegInfo<ELFT> Elf_RegInfo;
 
     for (const Elf_Shdr &section : this->_objFile->sections()) {
-      if (section.sh_type != llvm::ELF::SHT_MIPS_REGINFO)
-        continue;
-
-      auto contents = this->getSectionContents(&section);
-      if (error_code ec = contents.getError())
-        return ec;
-
-      // FIXME (simon): Show error in case of invalid section size.
-      if (contents.get().size() == sizeof(Elf_RegInfo)) {
-        const auto *regInfo =
-            reinterpret_cast<const Elf_RegInfo *>(contents.get().data());
-        _gp0 = regInfo->ri_gp_value;
-      }
-      break;
+      if (!_gp0.hasValue() && section.sh_type == llvm::ELF::SHT_MIPS_REGINFO) {
+        auto contents = this->getSectionContents(&section);
+        if (error_code ec = contents.getError())
+          return ec;
+
+        ArrayRef<uint8_t> raw = contents.get();
+
+        // FIXME (simon): Show error in case of invalid section size.
+        assert(raw.size() == sizeof(Elf_RegInfo) &&
+               "Invalid size of RegInfo section");
+        _gp0 = reinterpret_cast<const Elf_RegInfo *>(raw.data())->ri_gp_value;
+      } else if (!_tpOff.hasValue() && section.sh_flags & llvm::ELF::SHF_TLS)
+        _tpOff = section.sh_addr + TP_OFFSET;
     }
     return error_code::success();
   }
@@ -195,6 +201,8 @@ private:
     case llvm::ELF::R_MIPS_HI16:
     case llvm::ELF::R_MIPS_LO16:
     case llvm::ELF::R_MIPS_GOT16:
+    case llvm::ELF::R_MIPS_TLS_TPREL_HI16:
+    case llvm::ELF::R_MIPS_TLS_TPREL_LO16:
       return *(int16_t *)ap;
     default:
       return 0;

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp?rev=209582&r1=209581&r2=209582&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp Sat May 24 11:45:31 2014
@@ -101,6 +101,20 @@ static void relocCall16(uint8_t *locatio
   applyReloc(location, G, 0xffff);
 }
 
+/// \brief R_MIPS_TLS_TPREL_HI16
+/// (S + A) >> 16
+static void relocTLSTpRelHi16(uint8_t *location, uint64_t S, int64_t A) {
+  int32_t result = S + A + 0x8000;
+  applyReloc(location, result >> 16, 0xffff);
+}
+
+/// \brief R_MIPS_TLS_TPREL_LO16
+/// S + A
+static void relocTLSTpRelLo16(uint8_t *location, uint64_t S, int64_t A) {
+  int32_t result = S + A;
+  applyReloc(location, result, 0xffff);
+}
+
 /// \brief R_MIPS_GPREL32
 /// local: rel32 A + S + GP0 – GP (truncate)
 static void relocGPRel32(uint8_t *location, uint64_t P, uint64_t S, int64_t A,
@@ -162,6 +176,12 @@ error_code MipsTargetRelocationHandler::
   case R_MIPS_CALL16:
     relocCall16(location, relocVAddress, targetVAddress, ref.addend(), gpAddr);
     break;
+  case R_MIPS_TLS_TPREL_HI16:
+    relocTLSTpRelHi16(location, targetVAddress, ref.addend());
+    break;
+  case R_MIPS_TLS_TPREL_LO16:
+    relocTLSTpRelLo16(location, targetVAddress, ref.addend());
+    break;
   case R_MIPS_GPREL32:
     relocGPRel32(location, relocVAddress, targetVAddress, ref.addend(), gpAddr);
     break;

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp?rev=209582&r1=209581&r2=209582&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp Sat May 24 11:45:31 2014
@@ -205,6 +205,7 @@ private:
   void handle26(Reference &ref);
   void handleGOT(Reference &ref);
   void handleGPRel(const MipsELFDefinedAtom<ELFT> &atom, Reference &ref);
+  void handleTLS(const MipsELFDefinedAtom<ELFT> &atom, Reference &ref);
 
   const GOTAtom *getLocalGOTEntry(const Reference &ref);
   const GOTAtom *getGlobalGOTEntry(const Atom *a);
@@ -325,6 +326,10 @@ void RelocationPass<ELFT>::handleReferen
   case R_MIPS_GPREL32:
     handleGPRel(atom, ref);
     break;
+  case R_MIPS_TLS_TPREL_HI16:
+  case R_MIPS_TLS_TPREL_LO16:
+    handleTLS(atom, ref);
+    break;
   }
 }
 
@@ -508,6 +513,15 @@ void RelocationPass<ELFT>::handleGPRel(c
 }
 
 template <typename ELFT>
+void RelocationPass<ELFT>::handleTLS(const MipsELFDefinedAtom<ELFT> &atom,
+                                     Reference &ref) {
+  assert((ref.kindValue() == R_MIPS_TLS_TPREL_HI16 ||
+          ref.kindValue() == R_MIPS_TLS_TPREL_LO16) &&
+         "Unexpected kind of relocation");
+  ref.setAddend(ref.addend() - atom.file().getTPOffset());
+}
+
+template <typename ELFT>
 bool RelocationPass<ELFT>::isLocalCall(const Atom *a) const {
   Atom::Scope scope;
   if (auto *da = dyn_cast<DefinedAtom>(a))

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp?rev=209582&r1=209581&r2=209582&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp Sat May 24 11:45:31 2014
@@ -57,6 +57,8 @@ const Registry::KindStrings MipsTargetHa
   LLD_KIND_STRING_ENTRY(R_MIPS_CALL16),
   LLD_KIND_STRING_ENTRY(R_MIPS_GPREL32),
   LLD_KIND_STRING_ENTRY(R_MIPS_JALR),
+  LLD_KIND_STRING_ENTRY(R_MIPS_TLS_TPREL_HI16),
+  LLD_KIND_STRING_ENTRY(R_MIPS_TLS_TPREL_LO16),
   LLD_KIND_STRING_ENTRY(R_MIPS_COPY),
   LLD_KIND_STRING_ENTRY(R_MIPS_JUMP_SLOT),
   LLD_KIND_STRING_ENTRY(R_MIPS_PC32),

Added: lld/trunk/test/elf/Mips/tls-1.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/tls-1.test?rev=209582&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/tls-1.test (added)
+++ lld/trunk/test/elf/Mips/tls-1.test Sat May 24 11:45:31 2014
@@ -0,0 +1,63 @@
+# Check handling of R_MIPS_TLS_TPREL_HI16 / R_MIPS_TLS_TPREL_LO16 relocations.
+
+# RUN: yaml2obj -format=elf -o %t.o %s
+# RUN: lld -flavor gnu -target mipsel -e L0 -o %t.exe %t.o
+# RUN: llvm-objdump -s %t.exe | FileCheck %s
+
+# CHECK: Contents of section .text:
+# CHECK:  400160 00000000 01000000 03800000 04800000  ................
+
+!ELF
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_MIPS
+  Flags:           [ EF_MIPS_NOREORDER, EF_MIPS_CPIC,
+                     EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ]
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x10
+    Content:         '01000000020000000300000004000000'
+  - Name:            .rel.text
+    Type:            SHT_REL
+    Info:            .text
+    AddressAlign:    0x04
+    Relocations:
+      - Offset:          0x00
+        Symbol:          L1
+        Type:            R_MIPS_TLS_TPREL_HI16
+      - Offset:          0x04
+        Symbol:          L2
+        Type:            R_MIPS_TLS_TPREL_HI16
+      - Offset:          0x08
+        Symbol:          L2
+        Type:            R_MIPS_TLS_TPREL_LO16
+      - Offset:          0x0C
+        Symbol:          L1
+        Type:            R_MIPS_TLS_TPREL_LO16
+  - Name:            .tdata
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
+    AddressAlign:    0x04
+    Address:         0x1000
+    Size:            0x20000
+
+Symbols:
+  Global:
+    - Name:            L0
+      Type:            STT_FUNC
+      Section:         .text
+      Size:            0x58
+    - Name:            L1
+      Type:            STT_TLS
+      Section:         .tdata
+      Value:           0x00
+      Size:            0x04
+    - Name:            L2
+      Type:            STT_TLS
+      Section:         .tdata
+      Value:           0x10000
+      Size:            0x04





More information about the llvm-commits mailing list