[lld] r255884 - [ELF] - implemented @indntpoff (x86) relocation and its optimization.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 17 01:32:21 PST 2015


Author: grimar
Date: Thu Dec 17 03:32:21 2015
New Revision: 255884

URL: http://llvm.org/viewvc/llvm-project?rev=255884&view=rev
Log:
[ELF] - implemented @indntpoff (x86) relocation and its optimization.

@indntpoff is similar to @gotntpoff, but for use in position dependent code. While @gotntpoff resolves to GOT slot address relative to the
start of the GOT in the movl or addl instructions, @indntpoff resolves to the
absolute GOT slot address. ("ELF Handling For Thread-Local Storage", Ulrich Drepper).

Differential revision: http://reviews.llvm.org/D15494

Added:
    lld/trunk/test/ELF/Inputs/tls-opt-iele-i686-nopic.s
    lld/trunk/test/ELF/tls-opt-iele-i686-nopic.s
Modified:
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/Target.cpp
    lld/trunk/ELF/Target.h
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=255884&r1=255883&r2=255884&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Thu Dec 17 03:32:21 2015
@@ -198,11 +198,11 @@ void InputSectionBase<ELFT>::relocate(ui
     } else if (Target->relocNeedsGot(Type, Body)) {
       SymVA = Out<ELFT>::Got->getEntryAddr(Body);
       if (Body.isTls())
-        Type = Target->getTlsGotReloc();
+        Type = Target->getTlsGotReloc(Type);
     } else if (!Target->needsCopyRel(Type, Body) &&
                isa<SharedSymbol<ELFT>>(Body)) {
       continue;
-    } else if (Target->isTlsDynReloc(Type) ||
+    } else if (Target->isTlsDynReloc(Type, Body) ||
                Target->isSizeDynReloc(Type, Body)) {
       continue;
     } else if (Config->EMachine == EM_MIPS) {

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=255884&r1=255883&r2=255884&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Thu Dec 17 03:32:21 2015
@@ -263,10 +263,11 @@ template <class ELFT> void RelocationSec
     bool CanBePreempted = canBePreempted(Body, NeedsGot);
     bool LazyReloc = Body && Target->supportsLazyRelocations() &&
                      Target->relocNeedsPlt(Type, *Body);
+    bool IsDynRelative = Type == Target->getRelativeReloc();
 
     unsigned Sym = CanBePreempted ? Body->DynamicSymbolTableIndex : 0;
     unsigned Reloc;
-    if (!CanBePreempted)
+    if (!CanBePreempted || IsDynRelative)
       Reloc = Target->getRelativeReloc();
     else if (LazyReloc)
       Reloc = Target->getPltReloc();
@@ -297,7 +298,7 @@ template <class ELFT> void RelocationSec
     uintX_t Addend;
     if (NeedsCopy)
       Addend = 0;
-    else if (CanBePreempted)
+    else if (CanBePreempted || IsDynRelative)
       Addend = OrigAddend;
     else if (Body)
       Addend = getSymVA<ELFT>(cast<ELFSymbolBody<ELFT>>(*Body)) + OrigAddend;

Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=255884&r1=255883&r2=255884&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Thu Dec 17 03:32:21 2015
@@ -76,7 +76,8 @@ public:
   X86TargetInfo();
   void writeGotPltHeaderEntries(uint8_t *Buf) const override;
   unsigned getDynReloc(unsigned Type) const override;
-  bool isTlsDynReloc(unsigned Type) const override;
+  unsigned getTlsGotReloc(unsigned Type) const override;
+  bool isTlsDynReloc(unsigned Type, const SymbolBody &S) const override;
   void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
   void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
                          uint64_t PltEntryAddr) const override;
@@ -84,6 +85,7 @@ public:
                      uint64_t PltEntryAddr, int32_t Index,
                      unsigned RelOff) const override;
   bool needsCopyRel(uint32_t Type, const SymbolBody &S) const override;
+  bool relocNeedsDynRelative(unsigned Type) const override;
   bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
   bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
   void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
@@ -101,15 +103,15 @@ private:
                          uint64_t SA) const;
   void relocateTlsGdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
                          uint64_t SA) const;
-  void relocateTlsIeToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
-                         uint64_t SA) const;
+  void relocateTlsIeToLe(unsigned Type, uint8_t *Loc, uint8_t *BufEnd,
+                         uint64_t P, uint64_t SA) const;
 };
 
 class X86_64TargetInfo final : public TargetInfo {
 public:
   X86_64TargetInfo();
   unsigned getPltRefReloc(unsigned Type) const override;
-  bool isTlsDynReloc(unsigned Type) const override;
+  bool isTlsDynReloc(unsigned Type, const SymbolBody &S) const override;
   void writeGotPltHeaderEntries(uint8_t *Buf) const override;
   void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
   void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
@@ -253,6 +255,7 @@ X86TargetInfo::X86TargetInfo() {
   PCRelReloc = R_386_PC32;
   GotReloc = R_386_GLOB_DAT;
   PltReloc = R_386_JUMP_SLOT;
+  RelativeReloc = R_386_RELATIVE;
   TlsGotReloc = R_386_TLS_TPOFF;
   TlsGlobalDynamicReloc = R_386_TLS_GD;
   TlsLocalDynamicReloc = R_386_TLS_LDM;
@@ -280,10 +283,18 @@ unsigned X86TargetInfo::getDynReloc(unsi
   return Type;
 }
 
-bool X86TargetInfo::isTlsDynReloc(unsigned Type) const {
+unsigned X86TargetInfo::getTlsGotReloc(unsigned Type) const {
+  if (Type == R_386_TLS_IE)
+    return Type;
+  return TlsGotReloc;
+}
+
+bool X86TargetInfo::isTlsDynReloc(unsigned Type, const SymbolBody &S) const {
   if (Type == R_386_TLS_LE || Type == R_386_TLS_LE_32 ||
       Type == R_386_TLS_GOTIE)
     return Config->Shared;
+  if (Type == R_386_TLS_IE)
+    return canBePreempted(&S, true);
   return Type == R_386_TLS_GD;
 }
 
@@ -337,7 +348,7 @@ bool X86TargetInfo::needsCopyRel(uint32_
 bool X86TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
   if (S.isTls() && Type == R_386_TLS_GD)
     return Target->isTlsOptimized(Type, &S) && canBePreempted(&S, true);
-  if (Type == R_386_TLS_GOTIE)
+  if (Type == R_386_TLS_GOTIE || Type == R_386_TLS_IE)
     return !isTlsOptimized(Type, &S);
   return Type == R_386_GOT32 || relocNeedsPlt(Type, S);
 }
@@ -373,6 +384,7 @@ void X86TargetInfo::relocateOne(uint8_t
     write32le(Loc, V);
     break;
   }
+  case R_386_TLS_IE:
   case R_386_TLS_LDO_32:
     write32le(Loc, SA);
     break;
@@ -392,9 +404,14 @@ bool X86TargetInfo::isTlsOptimized(unsig
     return false;
   return Type == R_386_TLS_LDO_32 || Type == R_386_TLS_LDM ||
          Type == R_386_TLS_GD ||
+         (Type == R_386_TLS_IE && !canBePreempted(S, true)) ||
          (Type == R_386_TLS_GOTIE && !canBePreempted(S, true));
 }
 
+bool X86TargetInfo::relocNeedsDynRelative(unsigned Type) const {
+  return Config->Shared && Type == R_386_TLS_IE;
+}
+
 unsigned X86TargetInfo::relocateTlsOptimize(uint8_t *Loc, uint8_t *BufEnd,
                                             uint32_t Type, uint64_t P,
                                             uint64_t SA,
@@ -408,7 +425,8 @@ unsigned X86TargetInfo::relocateTlsOptim
     // The next relocation should be against __tls_get_addr, so skip it
     return 1;
   case R_386_TLS_GOTIE:
-    relocateTlsIeToLe(Loc, BufEnd, P, SA);
+  case R_386_TLS_IE:
+    relocateTlsIeToLe(Type, Loc, BufEnd, P, SA);
     return 0;
   case R_386_TLS_LDM:
     relocateTlsLdToLe(Loc, BufEnd, P, SA);
@@ -478,27 +496,47 @@ void X86TargetInfo::relocateTlsLdToLe(ui
   memcpy(Loc - 2, Inst, sizeof(Inst));
 }
 
-// In some conditions, R_386_TLS_GOTIE relocation can be optimized to
-// R_386_TLS_LE so that it does not use GOT.
-// This function does that. Read "ELF Handling For Thread-Local Storage,
-// 5.1  IA-32 Linker Optimizations" (http://www.akkadia.org/drepper/tls.pdf)
+// In some conditions, relocations can be optimized to avoid using GOT.
+// This function does that for Initial Exec to Local Exec case.
+// Read "ELF Handling For Thread-Local Storage, 5.1
+// IA-32 Linker Optimizations" (http://www.akkadia.org/drepper/tls.pdf)
 // by Ulrich Drepper for details.
-void X86TargetInfo::relocateTlsIeToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
+void X86TargetInfo::relocateTlsIeToLe(unsigned Type, uint8_t *Loc,
+                                      uint8_t *BufEnd, uint64_t P,
                                       uint64_t SA) const {
-  // Ulrich's document section 6.2 says that @gotntpoff can be
-  // used with MOVL or ADDL instructions.
-  // "MOVL foo at GOTTPOFF(%RIP), %REG" is transformed to "MOVL $foo, %REG".
-  // "ADDL foo at GOTNTPOFF(%RIP), %REG" is transformed to "LEAL foo(%REG), %REG"
-  // Note: gold converts to ADDL instead of LEAL.
+  // Ulrich's document section 6.2 says that @gotntpoff can
+  // be used with MOVL or ADDL instructions.
+  // @indntpoff is similar to @gotntpoff, but for use in
+  // position dependent code.
   uint8_t *Inst = Loc - 2;
-  uint8_t *RegSlot = Loc - 1;
+  uint8_t *Op = Loc - 1;
   uint8_t Reg = (Loc[-1] >> 3) & 7;
   bool IsMov = *Inst == 0x8b;
-  *Inst = IsMov ? 0xc7 : 0x8d;
-  if (IsMov)
-    *RegSlot = 0xc0 | ((*RegSlot >> 3) & 7);
-  else
-    *RegSlot = 0x80 | Reg | (Reg << 3);
+  if (Type == R_386_TLS_IE) {
+    // For R_386_TLS_IE relocation we perform the next transformations:
+    // MOVL foo at INDNTPOFF,%EAX is transformed to MOVL $foo,%EAX
+    // MOVL foo at INDNTPOFF,%REG is transformed to MOVL $foo,%REG
+    // ADDL foo at INDNTPOFF,%REG is transformed to ADDL $foo,%REG
+    // First one is special because when EAX is used the sequence is 5 bytes
+    // long, otherwise it is 6 bytes.
+    if (*Op == 0xa1) {
+      *Op = 0xb8;
+    } else {
+      *Inst = IsMov ? 0xc7 : 0x81;
+      *Op = 0xc0 | ((*Op >> 3) & 7);
+    }
+  } else {
+    // R_386_TLS_GOTIE relocation can be optimized to
+    // R_386_TLS_LE so that it does not use GOT.
+    // "MOVL foo at GOTTPOFF(%RIP), %REG" is transformed to "MOVL $foo, %REG".
+    // "ADDL foo at GOTNTPOFF(%RIP), %REG" is transformed to "LEAL foo(%REG), %REG"
+    // Note: gold converts to ADDL instead of LEAL.
+    *Inst = IsMov ? 0xc7 : 0x8d;
+    if (IsMov)
+      *Op = 0xc0 | ((*Op >> 3) & 7);
+    else
+      *Op = 0x80 | Reg | (Reg << 3);
+  }
   relocateOne(Loc, BufEnd, R_386_TLS_LE, P, SA);
 }
 
@@ -571,7 +609,7 @@ bool X86_64TargetInfo::relocNeedsGot(uin
   return Type == R_X86_64_GOTPCREL || relocNeedsPlt(Type, S);
 }
 
-bool X86_64TargetInfo::isTlsDynReloc(unsigned Type) const {
+bool X86_64TargetInfo::isTlsDynReloc(unsigned Type, const SymbolBody &S) const {
   return Type == R_X86_64_GOTTPOFF || Type == R_X86_64_TLSGD;
 }
 

Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=255884&r1=255883&r2=255884&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Thu Dec 17 03:32:21 2015
@@ -27,7 +27,6 @@ public:
   unsigned getGotReloc() const { return GotReloc; }
   unsigned getPltReloc() const { return PltReloc; }
   unsigned getRelativeReloc() const { return RelativeReloc; }
-  unsigned getTlsGotReloc() const { return TlsGotReloc; }
   bool isTlsLocalDynamicReloc(unsigned Type) const {
     return Type == TlsLocalDynamicReloc;
   }
@@ -42,8 +41,13 @@ public:
   unsigned getGotHeaderEntriesNum() const { return GotHeaderEntriesNum; }
   unsigned getGotPltHeaderEntriesNum() const { return GotPltHeaderEntriesNum; }
   virtual unsigned getDynReloc(unsigned Type) const { return Type; }
-  virtual bool isTlsDynReloc(unsigned Type) const { return false; }
+  virtual bool isTlsDynReloc(unsigned Type, const SymbolBody &S) const {
+    return false;
+  }
   virtual unsigned getPltRefReloc(unsigned Type) const;
+  virtual unsigned getTlsGotReloc(unsigned Type = -1) const {
+    return TlsGotReloc;
+  }
   virtual void writeGotHeaderEntries(uint8_t *Buf) const;
   virtual void writeGotPltHeaderEntries(uint8_t *Buf) const;
   virtual void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const = 0;
@@ -54,6 +58,7 @@ public:
                              int32_t Index, unsigned RelOff) const = 0;
   virtual bool isRelRelative(uint32_t Type) const;
   virtual bool isSizeDynReloc(uint32_t Type, const SymbolBody &S) const;
+  virtual bool relocNeedsDynRelative(unsigned Type) const { return false; }
   virtual bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const = 0;
   virtual bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const = 0;
   virtual void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=255884&r1=255883&r2=255884&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Dec 17 03:32:21 2015
@@ -236,9 +236,16 @@ void Writer<ELFT>::scanRelocs(
         continue;
     }
 
-    if (Body && Body->isTls() && !Target->isTlsDynReloc(Type))
+    if (Body && Body->isTls() && !Target->isTlsDynReloc(Type, *Body))
       continue;
 
+    if (Target->relocNeedsDynRelative(Type)) {
+      RelType *Rel = new (Alloc) RelType;
+      Rel->setSymbolAndType(0, Target->getRelativeReloc(), Config->Mips64EL);
+      Rel->r_offset = RI.r_offset;
+      Out<ELFT>::RelaDyn->addReloc({&C, Rel});
+    }
+
     bool NeedsGot = false;
     bool NeedsPlt = false;
     if (Body) {

Added: lld/trunk/test/ELF/Inputs/tls-opt-iele-i686-nopic.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/tls-opt-iele-i686-nopic.s?rev=255884&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/tls-opt-iele-i686-nopic.s (added)
+++ lld/trunk/test/ELF/Inputs/tls-opt-iele-i686-nopic.s Thu Dec 17 03:32:21 2015
@@ -0,0 +1,15 @@
+.type tlsshared0, at object
+.section .tbss,"awT", at nobits
+.globl tlsshared0
+.align 4
+tlsshared0:
+ .long 0
+ .size tlsshared0, 4
+
+.type tlsshared1, at object
+.section .tbss,"awT", at nobits
+.globl tlsshared1
+.align 4
+tlsshared1:
+ .long 0
+ .size tlsshared1, 4

Added: lld/trunk/test/ELF/tls-opt-iele-i686-nopic.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/tls-opt-iele-i686-nopic.s?rev=255884&view=auto
==============================================================================
--- lld/trunk/test/ELF/tls-opt-iele-i686-nopic.s (added)
+++ lld/trunk/test/ELF/tls-opt-iele-i686-nopic.s Thu Dec 17 03:32:21 2015
@@ -0,0 +1,159 @@
+// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %p/Inputs/tls-opt-iele-i686-nopic.s -o %tso.o
+// RUN: ld.lld -shared %tso.o -o %tso
+// RUN: ld.lld %t.o %tso -o %t1
+// RUN: llvm-readobj -s -r %t1 | FileCheck --check-prefix=GOTREL %s
+// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s
+// RUN: ld.lld -shared %t.o %tso -o %t1
+// RUN: llvm-readobj -s -r %t1 | FileCheck --check-prefix=GOTRELSHARED %s
+// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASMSHARED %s
+
+// GOTREL:      Section {
+// GOTREL:        Index:
+// GOTREL:        Name: .got
+// GOTREL-NEXT:   Type: SHT_PROGBITS
+// GOTREL-NEXT:   Flags [
+// GOTREL-NEXT:     SHF_ALLOC
+// GOTREL-NEXT:     SHF_WRITE
+// GOTREL-NEXT:   ]
+// GOTREL-NEXT:   Address: 0x12050
+// GOTREL-NEXT:   Offset: 0x2050
+// GOTREL-NEXT:   Size: 8
+// GOTREL-NEXT:   Link: 0
+// GOTREL-NEXT:   Info: 0
+// GOTREL-NEXT:   AddressAlignment: 4
+// GOTREL-NEXT:   EntrySize: 0
+// GOTREL-NEXT: }
+// GOTREL:      Relocations [
+// GOTREL-NEXT: Section ({{.*}}) .rel.dyn {
+// GOTREL-NEXT:   0x12050 R_386_TLS_TPOFF tlsshared0 0x0
+// GOTREL-NEXT:   0x12054 R_386_TLS_TPOFF tlsshared1 0x0
+// GOTREL-NEXT:  }
+// GOTREL-NEXT: ]
+
+// DISASM:      Disassembly of section .text:
+// DISASM-NEXT: _start:
+// 4294967288 = 0xFFFFFFF8
+// 4294967292 = 0xFFFFFFFC
+// 73808 = (.got)[0] = 0x12050
+// 73812 = (.got)[1] = 0x12054
+// DISASM-NEXT: 11000: c7 c1 f8 ff ff ff movl $4294967288, %ecx
+// DISASM-NEXT: 11006: 65 8b 01          movl %gs:(%ecx), %eax
+// DISASM-NEXT: 11009: b8 f8 ff ff ff    movl $4294967288, %eax
+// DISASM-NEXT: 1100e: 65 8b 00          movl %gs:(%eax), %eax
+// DISASM-NEXT: 11011: 81 c1 f8 ff ff ff addl $4294967288, %ecx
+// DISASM-NEXT: 11017: 65 8b 01          movl %gs:(%ecx), %eax
+// DISASM-NEXT: 1101a: c7 c1 fc ff ff ff movl $4294967292, %ecx
+// DISASM-NEXT: 11020: 65 8b 01          movl %gs:(%ecx), %eax
+// DISASM-NEXT: 11023: b8 fc ff ff ff    movl $4294967292, %eax
+// DISASM-NEXT: 11028: 65 8b 00          movl %gs:(%eax), %eax
+// DISASM-NEXT: 1102b: 81 c1 fc ff ff ff addl $4294967292, %ecx
+// DISASM-NEXT: 11031: 65 8b 01          movl %gs:(%ecx), %eax
+// DISASM-NEXT: 11034: 8b 0d 50 20 01 00 movl 73808, %ecx
+// DISASM-NEXT: 1103a: 65 8b 01          movl %gs:(%ecx), %eax
+// DISASM-NEXT: 1103d: 03 0d 54 20 01 00 addl 73812, %ecx
+// DISASM-NEXT: 11043: 65 8b 01          movl %gs:(%ecx), %eax
+
+// GOTRELSHARED:     Section {
+// GOTRELSHARED:      Index: 8
+// GOTRELSHARED:      Name: .got
+// GOTRELSHARED-NEXT:   Type: SHT_PROGBITS
+// GOTRELSHARED-NEXT:   Flags [
+// GOTRELSHARED-NEXT:     SHF_ALLOC
+// GOTRELSHARED-NEXT:     SHF_WRITE
+// GOTRELSHARED-NEXT:   ]
+// GOTRELSHARED-NEXT:   Address: 0x2050
+// GOTRELSHARED-NEXT:   Offset: 0x2050
+// GOTRELSHARED-NEXT:   Size: 16
+// GOTRELSHARED-NEXT:   Link: 0
+// GOTRELSHARED-NEXT:   Info: 0
+// GOTRELSHARED-NEXT:   AddressAlignment: 4
+// GOTRELSHARED-NEXT:   EntrySize: 0
+// GOTRELSHARED-NEXT: }
+// GOTRELSHARED:      Relocations [
+// GOTRELSHARED-NEXT:   Section ({{.*}}) .rel.dyn {
+// GOTRELSHARED-NEXT:     0x1002 R_386_RELATIVE - 0x0
+// GOTRELSHARED-NEXT:     0x2050 R_386_TLS_TPOFF tlslocal0 0x0
+// GOTRELSHARED-NEXT:     0x100A R_386_RELATIVE - 0x0
+// GOTRELSHARED-NEXT:     0x1013 R_386_RELATIVE - 0x0
+// GOTRELSHARED-NEXT:     0x101C R_386_RELATIVE - 0x0
+// GOTRELSHARED-NEXT:     0x2054 R_386_TLS_TPOFF tlslocal1 0x0
+// GOTRELSHARED-NEXT:     0x1024 R_386_RELATIVE - 0x0
+// GOTRELSHARED-NEXT:     0x102D R_386_RELATIVE - 0x0
+// GOTRELSHARED-NEXT:     0x1036 R_386_RELATIVE - 0x0
+// GOTRELSHARED-NEXT:     0x2058 R_386_TLS_TPOFF tlsshared0 0x0
+// GOTRELSHARED-NEXT:     0x103F R_386_RELATIVE - 0x0
+// GOTRELSHARED-NEXT:     0x205C R_386_TLS_TPOFF tlsshared1 0x0
+// GOTRELSHARED-NEXT:   }
+// GOTRELSHARED-NEXT: ]
+
+// DISASMSHARED:       Disassembly of section .text:
+// DISASMSHARED-NEXT:  _start:
+// (.got)[0] = 0x2050 = 8272
+// (.got)[1] = 0x2054 = 8276
+// (.got)[2] = 0x2058 = 8280
+// (.got)[3] = 0x205C = 8284
+// DISASMSHARED-NEXT:  1000: 8b 0d 50 20 00 00 movl 8272, %ecx
+// DISASMSHARED-NEXT:  1006: 65 8b 01          movl %gs:(%ecx), %eax
+// DISASMSHARED-NEXT:  1009: a1 50 20 00 00    movl 8272, %eax
+// DISASMSHARED-NEXT:  100e: 65 8b 00          movl %gs:(%eax), %eax
+// DISASMSHARED-NEXT:  1011: 03 0d 50 20 00 00 addl 8272, %ecx
+// DISASMSHARED-NEXT:  1017: 65 8b 01          movl %gs:(%ecx), %eax
+// DISASMSHARED-NEXT:  101a: 8b 0d 54 20 00 00 movl 8276, %ecx
+// DISASMSHARED-NEXT:  1020: 65 8b 01          movl %gs:(%ecx), %eax
+// DISASMSHARED-NEXT:  1023: a1 54 20 00 00    movl 8276, %eax
+// DISASMSHARED-NEXT:  1028: 65 8b 00          movl %gs:(%eax), %eax
+// DISASMSHARED-NEXT:  102b: 03 0d 54 20 00 00 addl 8276, %ecx
+// DISASMSHARED-NEXT:  1031: 65 8b 01          movl %gs:(%ecx), %eax
+// DISASMSHARED-NEXT:  1034: 8b 0d 58 20 00 00 movl 8280, %ecx
+// DISASMSHARED-NEXT:  103a: 65 8b 01          movl %gs:(%ecx), %eax
+// DISASMSHARED-NEXT:  103d: 03 0d 5c 20 00 00 addl 8284, %ecx
+// DISASMSHARED-NEXT:  1043: 65 8b 01          movl %gs:(%ecx), %eax
+
+.type tlslocal0, at object
+.section .tbss,"awT", at nobits
+.globl tlslocal0
+.align 4
+tlslocal0:
+ .long 0
+ .size tlslocal0, 4
+
+.type tlslocal1, at object
+.section .tbss,"awT", at nobits
+.globl tlslocal1
+.align 4
+tlslocal1:
+ .long 0
+ .size tlslocal1, 4
+
+.section .text
+.globl ___tls_get_addr
+.type ___tls_get_addr, at function
+___tls_get_addr:
+
+.section .text
+.globl _start
+_start:
+movl tlslocal0 at indntpoff,%ecx
+movl %gs:(%ecx),%eax
+
+movl tlslocal0 at indntpoff,%eax
+movl %gs:(%eax),%eax
+
+addl tlslocal0 at indntpoff,%ecx
+movl %gs:(%ecx),%eax
+
+movl tlslocal1 at indntpoff,%ecx
+movl %gs:(%ecx),%eax
+
+movl tlslocal1 at indntpoff,%eax
+movl %gs:(%eax),%eax
+
+addl tlslocal1 at indntpoff,%ecx
+movl %gs:(%ecx),%eax
+
+movl tlsshared0 at indntpoff,%ecx
+movl %gs:(%ecx),%eax
+
+addl tlsshared1 at indntpoff,%ecx
+movl %gs:(%ecx),%eax




More information about the llvm-commits mailing list