[LLD][ELF] - Set DF_STATIC_TLS flag for i386 target.

DF_STATIC_TLS flag indicates that the shared object or executable
contains code using a static thread-local storage scheme.

Patch checks if IE/LE relocations were used to check if the code uses
a static model. If so it sets the DF_STATIC_TLS flag.

Differential revision: https://reviews.llvm.org/D57749

git-svn-id: https://llvm.org/svn/llvm-project/lld/trunk@353293 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/ELF/Arch/X86.cpp b/ELF/Arch/X86.cpp
index 061538d..0827dd3 100644
--- a/ELF/Arch/X86.cpp
+++ b/ELF/Arch/X86.cpp
@@ -72,6 +72,15 @@
 
 RelExpr X86::getRelExpr(RelType Type, const Symbol &S,
                         const uint8_t *Loc) const {
+  // There are 4 different TLS variable models with varying degrees of
+  // flexibility and performance. LocalExec and InitialExec models are fast but
+  // less-flexible models. They cannot be used for dlopen(). If they are in use,
+  // we set DF_STATIC_TLS in the ELF header so that the runtime can reject such
+  // DSOs.
+  if (Type == R_386_TLS_LE || Type == R_386_TLS_LE_32 || Type == R_386_TLS_IE ||
+      Type == R_386_TLS_GOTIE)
+    Config->HasStaticTlsModel = true;
+
   switch (Type) {
   case R_386_8:
   case R_386_16:
diff --git a/ELF/Config.h b/ELF/Config.h
index 8943ced..a12f8c9 100644
--- a/ELF/Config.h
+++ b/ELF/Config.h
@@ -17,6 +17,7 @@
 #include "llvm/Support/CachePruning.h"
 #include "llvm/Support/CodeGen.h"
 #include "llvm/Support/Endian.h"
+#include <atomic>
 #include <vector>
 
 namespace lld {
@@ -80,6 +81,7 @@
 // and such fields have the same name as the corresponding options.
 // Most fields are initialized by the driver.
 struct Configuration {
+  std::atomic<bool> HasStaticTlsModel = false;
   uint8_t OSABI = 0;
   llvm::CachePruningPolicy ThinLTOCachePolicy;
   llvm::StringMap<uint64_t> SectionStartMap;
diff --git a/ELF/SyntheticSections.cpp b/ELF/SyntheticSections.cpp
index 5073598..f1b5c77 100644
--- a/ELF/SyntheticSections.cpp
+++ b/ELF/SyntheticSections.cpp
@@ -1295,6 +1295,8 @@
   }
   if (!Config->ZText)
     DtFlags |= DF_TEXTREL;
+  if (Config->HasStaticTlsModel)
+    DtFlags |= DF_STATIC_TLS;
 
   if (DtFlags)
     addInt(DT_FLAGS, DtFlags);
diff --git a/test/ELF/Inputs/i386-static-tls-model1.s b/test/ELF/Inputs/i386-static-tls-model1.s
new file mode 100644
index 0000000..d287fb6
--- /dev/null
+++ b/test/ELF/Inputs/i386-static-tls-model1.s
@@ -0,0 +1,9 @@
+.section ".tdata", "awT", @progbits
+.globl var
+var:
+
+.section .foo, "aw"
+.global _start
+_start:
+ movl $var@tpoff, %edx # R_386_TLS_LE_32
+ movl %gs:0, %ecx
diff --git a/test/ELF/Inputs/i386-static-tls-model2.s b/test/ELF/Inputs/i386-static-tls-model2.s
new file mode 100644
index 0000000..2c01cee
--- /dev/null
+++ b/test/ELF/Inputs/i386-static-tls-model2.s
@@ -0,0 +1,9 @@
+.section ".tdata", "awT", @progbits
+.globl var
+var:
+
+.section .foo, "aw"
+.global _start
+_start: 
+ movl %gs:0, %eax
+ addl var@gotntpoff(%ebx), %eax # R_386_TLS_GOTIE
diff --git a/test/ELF/Inputs/i386-static-tls-model3.s b/test/ELF/Inputs/i386-static-tls-model3.s
new file mode 100644
index 0000000..fd18fce
--- /dev/null
+++ b/test/ELF/Inputs/i386-static-tls-model3.s
@@ -0,0 +1,9 @@
+.section ".tdata", "awT", @progbits
+.globl var
+var:
+
+.section .foo, "aw"
+.global _start
+_start:
+ movl %gs:0, %eax
+ addl var@indntpoff, %eax # R_386_TLS_IE
diff --git a/test/ELF/Inputs/i386-static-tls-model4.s b/test/ELF/Inputs/i386-static-tls-model4.s
new file mode 100644
index 0000000..6006518
--- /dev/null
+++ b/test/ELF/Inputs/i386-static-tls-model4.s
@@ -0,0 +1,9 @@
+.section ".tdata", "awT", @progbits
+.globl var
+var:
+
+.section .foo, "aw"
+.global _start
+_start:
+ movl %gs:0, %eax
+ leal var@ntpoff(%eax), %eax # R_386_TLS_LE
diff --git a/test/ELF/i386-static-tls-model.s b/test/ELF/i386-static-tls-model.s
new file mode 100644
index 0000000..a6dbc6d
--- /dev/null
+++ b/test/ELF/i386-static-tls-model.s
@@ -0,0 +1,20 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %S/Inputs/i386-static-tls-model1.s -o %t.o
+# RUN: ld.lld %t.o -o %t1 -shared
+# RUN: llvm-readobj -dynamic-table %t1 | FileCheck %s
+
+# RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %S/Inputs/i386-static-tls-model2.s -o %t.o
+# RUN: ld.lld %t.o -o %t2 -shared
+# RUN: llvm-readobj -dynamic-table %t2 | FileCheck %s
+
+# RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %S/Inputs/i386-static-tls-model3.s -o %t.o
+# RUN: ld.lld %t.o -o %t3 -shared
+# RUN: llvm-readobj -dynamic-table %t3 | FileCheck %s
+
+# RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %S/Inputs/i386-static-tls-model4.s -o %t.o
+# RUN: ld.lld %t.o -o %t4 -shared
+# RUN: llvm-readobj -dynamic-table %t4 | FileCheck %s
+
+# CHECK: DynamicSection [
+# CHECK: FLAGS STATIC_TLS
diff --git a/test/ELF/i386-tls-ie-shared.s b/test/ELF/i386-tls-ie-shared.s
index 9e5ed1b..0e9694f 100644
--- a/test/ELF/i386-tls-ie-shared.s
+++ b/test/ELF/i386-tls-ie-shared.s
@@ -14,8 +14,8 @@
 // GOTRELSHARED-NEXT:     SHF_ALLOC
 // GOTRELSHARED-NEXT:     SHF_WRITE
 // GOTRELSHARED-NEXT:   ]
-// GOTRELSHARED-NEXT:   Address: 0x2058
-// GOTRELSHARED-NEXT:   Offset: 0x2058
+// GOTRELSHARED-NEXT:   Address: 0x2060
+// GOTRELSHARED-NEXT:   Offset: 0x2060
 // GOTRELSHARED-NEXT:   Size: 16
 // GOTRELSHARED-NEXT:   Link: 0
 // GOTRELSHARED-NEXT:   Info: 0
@@ -32,36 +32,36 @@
 // GOTRELSHARED-NEXT:     0x102D R_386_RELATIVE - 0x0
 // GOTRELSHARED-NEXT:     0x1036 R_386_RELATIVE - 0x0
 // GOTRELSHARED-NEXT:     0x103F R_386_RELATIVE - 0x0
-// GOTRELSHARED-NEXT:     0x2058 R_386_TLS_TPOFF tlslocal0 0x0
-// GOTRELSHARED-NEXT:     0x205C R_386_TLS_TPOFF tlslocal1 0x0
-// GOTRELSHARED-NEXT:     0x2060 R_386_TLS_TPOFF tlsshared0 0x0
-// GOTRELSHARED-NEXT:     0x2064 R_386_TLS_TPOFF tlsshared1 0x0
+// GOTRELSHARED-NEXT:     0x2060 R_386_TLS_TPOFF tlslocal0 0x0
+// GOTRELSHARED-NEXT:     0x2064 R_386_TLS_TPOFF tlslocal1 0x0
+// GOTRELSHARED-NEXT:     0x2068 R_386_TLS_TPOFF tlsshared0 0x0
+// GOTRELSHARED-NEXT:     0x206C R_386_TLS_TPOFF tlsshared1 0x0
 // GOTRELSHARED-NEXT:   }
 // GOTRELSHARED-NEXT: ]
 // GOTRELSHARED:      0x6FFFFFFA RELCOUNT             8
 
 // DISASMSHARED:       Disassembly of section test:
 // DISASMSHARED-NEXT:  _start:
-// (.got)[0] = 0x2058 = 8280
-// (.got)[1] = 0x205C = 8284
-// (.got)[2] = 0x2060 = 8288
-// (.got)[3] = 0x2064 = 8292
-// DISASMSHARED-NEXT:  1000: 8b 0d 58 20 00 00   movl  8280, %ecx
-// DISASMSHARED-NEXT:  1006: 65 8b 01  movl  %gs:(%ecx), %eax
-// DISASMSHARED-NEXT:  1009: a1 58 20 00 00  movl  8280, %eax
-// DISASMSHARED-NEXT:  100e: 65 8b 00  movl  %gs:(%eax), %eax
-// DISASMSHARED-NEXT:  1011: 03 0d 58 20 00 00   addl  8280, %ecx
-// DISASMSHARED-NEXT:  1017: 65 8b 01  movl  %gs:(%ecx), %eax
-// DISASMSHARED-NEXT:  101a: 8b 0d 5c 20 00 00   movl  8284, %ecx
-// DISASMSHARED-NEXT:  1020: 65 8b 01  movl  %gs:(%ecx), %eax
-// DISASMSHARED-NEXT:  1023: a1 5c 20 00 00  movl  8284, %eax
-// DISASMSHARED-NEXT:  1028: 65 8b 00  movl  %gs:(%eax), %eax
-// DISASMSHARED-NEXT:  102b: 03 0d 5c 20 00 00   addl  8284, %ecx
-// DISASMSHARED-NEXT:  1031: 65 8b 01  movl  %gs:(%ecx), %eax
-// DISASMSHARED-NEXT:  1034: 8b 0d 60 20 00 00   movl  8288, %ecx
-// DISASMSHARED-NEXT:  103a: 65 8b 01  movl  %gs:(%ecx), %eax
-// DISASMSHARED-NEXT:  103d: 03 0d 64 20 00 00   addl  8292, %ecx
-// DISASMSHARED-NEXT:  1043: 65 8b 01  movl  %gs:(%ecx), %eax
+// (.got)[0] = 0x2060 = 8288
+// (.got)[1] = 0x2064 = 8292
+// (.got)[2] = 0x2068 = 8296
+// (.got)[3] = 0x206C = 8300
+// DISASMSHARED-NEXT:  1000: {{.*}} movl  8288, %ecx
+// DISASMSHARED-NEXT:  1006: {{.*}} movl  %gs:(%ecx), %eax
+// DISASMSHARED-NEXT:  1009: {{.*}} movl  8288, %eax
+// DISASMSHARED-NEXT:  100e: {{.*}} movl  %gs:(%eax), %eax
+// DISASMSHARED-NEXT:  1011: {{.*}} addl  8288, %ecx
+// DISASMSHARED-NEXT:  1017: {{.*}} movl  %gs:(%ecx), %eax
+// DISASMSHARED-NEXT:  101a: {{.*}} movl  8292, %ecx
+// DISASMSHARED-NEXT:  1020: {{.*}} movl  %gs:(%ecx), %eax
+// DISASMSHARED-NEXT:  1023: {{.*}} movl  8292, %eax
+// DISASMSHARED-NEXT:  1028: {{.*}} movl  %gs:(%eax), %eax
+// DISASMSHARED-NEXT:  102b: {{.*}} addl  8292, %ecx
+// DISASMSHARED-NEXT:  1031: {{.*}} movl  %gs:(%ecx), %eax
+// DISASMSHARED-NEXT:  1034: {{.*}} movl  8296, %ecx
+// DISASMSHARED-NEXT:  103a: {{.*}} movl  %gs:(%ecx), %eax
+// DISASMSHARED-NEXT:  103d: {{.*}} addl  8300, %ecx
+// DISASMSHARED-NEXT:  1043: {{.*}} movl  %gs:(%ecx), %eax
 
 .type tlslocal0,@object
 .section .tbss,"awT",@nobits
diff --git a/test/ELF/tls-dynamic-i686.s b/test/ELF/tls-dynamic-i686.s
index 1b13f26..dc651d0 100644
--- a/test/ELF/tls-dynamic-i686.s
+++ b/test/ELF/tls-dynamic-i686.s
@@ -56,8 +56,8 @@
 // CHECK-NEXT:   SHF_ALLOC
 // CHECK-NEXT:   SHF_WRITE
 // CHECK-NEXT: ]
-// CHECK-NEXT: Address: 0x3068
-// CHECK-NEXT: Offset: 0x3068
+// CHECK-NEXT: Address: 0x3070
+// CHECK-NEXT: Offset: 0x3070
 // CHECK-NEXT: Size: 32
 // CHECK-NEXT: Link: 0
 // CHECK-NEXT: Info: 0
@@ -66,13 +66,13 @@
 
 // CHECK: Relocations [
 // CHECK:      Section ({{.+}}) .rel.dyn {
-// CHECK-NEXT: 0x3078 R_386_TLS_DTPMOD32 - 0x0
-// CHECK-NEXT: 0x3068 R_386_TLS_DTPMOD32 tls0 0x0
-// CHECK-NEXT: 0x306C R_386_TLS_DTPOFF32 tls0 0x0
-// CHECK-NEXT: 0x3080 R_386_TLS_TPOFF tls0 0x0
-// CHECK-NEXT: 0x3070 R_386_TLS_DTPMOD32 tls1 0x0
-// CHECK-NEXT: 0x3074 R_386_TLS_DTPOFF32 tls1 0x0
-// CHECK-NEXT: 0x3084 R_386_TLS_TPOFF tls1 0x0
+// CHECK-NEXT: 0x3080 R_386_TLS_DTPMOD32 - 0x0
+// CHECK-NEXT: 0x3070 R_386_TLS_DTPMOD32 tls0 0x0
+// CHECK-NEXT: 0x3074 R_386_TLS_DTPOFF32 tls0 0x0
+// CHECK-NEXT: 0x3088 R_386_TLS_TPOFF tls0 0x0
+// CHECK-NEXT: 0x3078 R_386_TLS_DTPMOD32 tls1 0x0
+// CHECK-NEXT: 0x307C R_386_TLS_DTPOFF32 tls1 0x0
+// CHECK-NEXT: 0x308C R_386_TLS_TPOFF tls1 0x0
 // CHECK-NEXT: }
 
 // DIS:      Disassembly of section .text:
@@ -80,20 +80,20 @@
 // General dynamic model:
 // -32 and -24 are first and second GOT entries offsets.
 // Each one is a pair of records.
-// DIS-NEXT: 1000: 8d 04 1d e0 ff ff ff  leal -32(,%ebx), %eax
-// DIS-NEXT: 1007: e8 64 00 00 00        calll 100
-// DIS-NEXT: 100c: 8d 04 1d e8 ff ff ff  leal -24(,%ebx), %eax
-// DIS-NEXT: 1013: e8 58 00 00 00        calll 88
+// DIS-NEXT: 1000: {{.*}} leal -32(,%ebx), %eax
+// DIS-NEXT: 1007: {{.*}} calll 100
+// DIS-NEXT: 100c: {{.*}} leal -24(,%ebx), %eax
+// DIS-NEXT: 1013: {{.*}} calll 88
 // Local dynamic model:
 // -16 is a local module tls index offset.
-// DIS-NEXT: 1018: 8d 83 f0 ff ff ff leal -16(%ebx), %eax
-// DIS-NEXT: 101e: e8 4d 00 00 00    calll 77
-// DIS-NEXT: 1023: 8d 90 08 00 00 00 leal 8(%eax), %edx
-// DIS-NEXT: 1029: 8d 83 f0 ff ff ff leal -16(%ebx), %eax
-// DIS-NEXT: 102f: e8 3c 00 00 00    calll 60
-// DIS-NEXT: 1034: 8d 90 0c 00 00 00 leal 12(%eax), %edx
+// DIS-NEXT: 1018: {{.*}} leal -16(%ebx), %eax
+// DIS-NEXT: 101e: {{.*}} calll 77
+// DIS-NEXT: 1023: {{.*}} leal 8(%eax), %edx
+// DIS-NEXT: 1029: {{.*}} leal -16(%ebx), %eax
+// DIS-NEXT: 102f: {{.*}} calll 60
+// DIS-NEXT: 1034: {{.*}} leal 12(%eax), %edx
 // Initial exec model:
-// DIS-NEXT: 103a: 65 a1 00 00 00 00 movl %gs:0, %eax
-// DIS-NEXT: 1040: 03 83 f8 ff ff ff addl -8(%ebx), %eax
-// DIS-NEXT: 1046: 65 a1 00 00 00 00 movl %gs:0, %eax
-// DIS-NEXT: 104c: 03 83 fc ff ff ff addl -4(%ebx), %eax
+// DIS-NEXT: 103a: {{.*}} movl %gs:0, %eax
+// DIS-NEXT: 1040: {{.*}} addl -8(%ebx), %eax
+// DIS-NEXT: 1046: {{.*}} movl %gs:0, %eax
+// DIS-NEXT: 104c: {{.*}} addl -4(%ebx), %eax
diff --git a/test/ELF/tls-opt-iele-i686-nopic.s b/test/ELF/tls-opt-iele-i686-nopic.s
index 704928b..9b97264 100644
--- a/test/ELF/tls-opt-iele-i686-nopic.s
+++ b/test/ELF/tls-opt-iele-i686-nopic.s
@@ -14,8 +14,8 @@
 // GOTREL-NEXT:     SHF_ALLOC
 // GOTREL-NEXT:     SHF_WRITE
 // GOTREL-NEXT:   ]
-// GOTREL-NEXT:   Address: 0x402058
-// GOTREL-NEXT:   Offset: 0x2058
+// GOTREL-NEXT:   Address:  0x402060
+// GOTREL-NEXT:   Offset: 0x2060
 // GOTREL-NEXT:   Size: 8
 // GOTREL-NEXT:   Link: 0
 // GOTREL-NEXT:   Info: 0
@@ -24,8 +24,8 @@
 // GOTREL-NEXT: }
 // GOTREL:      Relocations [
 // GOTREL-NEXT: Section ({{.*}}) .rel.dyn {
-// GOTREL-NEXT:   0x402058 R_386_TLS_TPOFF tlsshared0 0x0
-// GOTREL-NEXT:   0x40205C R_386_TLS_TPOFF tlsshared1 0x0
+// GOTREL-NEXT:   0x402060 R_386_TLS_TPOFF tlsshared0 0x0
+// GOTREL-NEXT:   0x402064 R_386_TLS_TPOFF tlsshared1 0x0
 // GOTREL-NEXT:  }
 // GOTREL-NEXT: ]
 
@@ -33,24 +33,24 @@
 // DISASM-NEXT: _start:
 // 4294967288 = 0xFFFFFFF8
 // 4294967292 = 0xFFFFFFFC
-// 4202584 = (.got)[0] = 0x402058
-// 4202588 = (.got)[1] = 0x40205C
-// DISASM-NEXT: 401000: c7 c1 f8 ff ff ff movl $4294967288, %ecx
-// DISASM-NEXT: 401006: 65 8b 01          movl %gs:(%ecx), %eax
-// DISASM-NEXT: 401009: b8 f8 ff ff ff    movl $4294967288, %eax
-// DISASM-NEXT: 40100e: 65 8b 00          movl %gs:(%eax), %eax
-// DISASM-NEXT: 401011: 81 c1 f8 ff ff ff addl $4294967288, %ecx
-// DISASM-NEXT: 401017: 65 8b 01          movl %gs:(%ecx), %eax
-// DISASM-NEXT: 40101a: c7 c1 fc ff ff ff movl $4294967292, %ecx
-// DISASM-NEXT: 401020: 65 8b 01          movl %gs:(%ecx), %eax
-// DISASM-NEXT: 401023: b8 fc ff ff ff    movl $4294967292, %eax
-// DISASM-NEXT: 401028: 65 8b 00          movl %gs:(%eax), %eax
-// DISASM-NEXT: 40102b: 81 c1 fc ff ff ff addl $4294967292, %ecx
-// DISASM-NEXT: 401031: 65 8b 01          movl %gs:(%ecx), %eax
-// DISASM-NEXT: 401034: 8b 0d 58 20 40 00 movl 4202584, %ecx
-// DISASM-NEXT: 40103a: 65 8b 01          movl %gs:(%ecx), %eax
-// DISASM-NEXT: 40103d: 03 0d 5c 20 40 00 addl 4202588, %ecx
-// DISASM-NEXT: 401043: 65 8b 01          movl %gs:(%ecx), %eax
+// 4202592 = (.got)[0] = 0x402060
+// 4202596 = (.got)[1] = 0x402064
+// DISASM-NEXT: 401000: {{.*}} movl $4294967288, %ecx
+// DISASM-NEXT: 401006: {{.*}} movl %gs:(%ecx), %eax
+// DISASM-NEXT: 401009: {{.*}} movl $4294967288, %eax
+// DISASM-NEXT: 40100e: {{.*}} movl %gs:(%eax), %eax
+// DISASM-NEXT: 401011: {{.*}} addl $4294967288, %ecx
+// DISASM-NEXT: 401017: {{.*}} movl %gs:(%ecx), %eax
+// DISASM-NEXT: 40101a: {{.*}} movl $4294967292, %ecx
+// DISASM-NEXT: 401020: {{.*}} movl %gs:(%ecx), %eax
+// DISASM-NEXT: 401023: {{.*}} movl $4294967292, %eax
+// DISASM-NEXT: 401028: {{.*}} movl %gs:(%eax), %eax
+// DISASM-NEXT: 40102b: {{.*}} addl $4294967292, %ecx
+// DISASM-NEXT: 401031: {{.*}} movl %gs:(%ecx), %eax
+// DISASM-NEXT: 401034: {{.*}} movl 4202592, %ecx
+// DISASM-NEXT: 40103a: {{.*}} movl %gs:(%ecx), %eax
+// DISASM-NEXT: 40103d: {{.*}} addl 4202596, %ecx
+// DISASM-NEXT: 401043: {{.*}} movl %gs:(%ecx), %eax
 
 .type tlslocal0,@object
 .section .tbss,"awT",@nobits