[lld] fb3c1b3 - [ELF] Reject local-exec TLS relocations for -shared

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 21 08:47:11 PST 2020


Author: Fangrui Song
Date: 2020-12-21T08:47:04-08:00
New Revision: fb3c1b3de5ce7342438d7451f01a14f9c52323cd

URL: https://github.com/llvm/llvm-project/commit/fb3c1b3de5ce7342438d7451f01a14f9c52323cd
DIFF: https://github.com/llvm/llvm-project/commit/fb3c1b3de5ce7342438d7451f01a14f9c52323cd.diff

LOG: [ELF] Reject local-exec TLS relocations for -shared

For x86-64, D33100 added a diagnostic for local-exec TLS relocations referencing a preemptible symbol.

This patch generalizes it to non-preemptible symbols (see `-Bsymbolic` in `tls.s`)
on all targets.

Local-exec TLS relocations resolve to offsets relative to a fixed point within
the static TLS block, which are only meaningful for the executable.

With this change, `clang -fpic -shared -fuse-ld=bfd a.c` on the following example will be flagged for AArch64/ARM/i386/x86-64/RISC-V

```
static __attribute__((tls_model("local-exec"))) __thread long TlsVar = 42;
long bump() { return ++TlsVar; }
```

Note, in GNU ld, at least arm, riscv and x86's ports have the similar
diagnostics, but aarch64 and ppc64 do not error.

Differential Revision: https://reviews.llvm.org/D93331

Added: 
    

Modified: 
    lld/ELF/Relocations.cpp
    lld/test/ELF/aarch64-tls-le.s
    lld/test/ELF/arm-tls-le32.s
    lld/test/ELF/i386-static-tls-model.s
    lld/test/ELF/i386-tls-le.s
    lld/test/ELF/i386-zrel-zrela.s
    lld/test/ELF/mips-tls-hilo.s
    lld/test/ELF/ppc64-local-exec-tls.s
    lld/test/ELF/riscv-tls-le.s
    lld/test/ELF/tls.s

Removed: 
    lld/test/ELF/Inputs/i386-static-tls-model4.s
    lld/test/ELF/x86-64-reloc-tpoff32-fpic.s


################################################################################
diff  --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index a9f627a08057..875ecf78ca2c 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1400,10 +1400,17 @@ static void scanReloc(InputSectionBase &sec, OffsetGetter &getOffset, RelTy *&i,
     in.got->hasGotOffRel = true;
   }
 
-  // Process some TLS relocations, including relaxing TLS relocations.
-  // Note that this function does not handle all TLS relocations.
-  if (unsigned processed =
-          handleTlsRelocation<ELFT>(type, sym, sec, offset, addend, expr)) {
+  // Process TLS relocations, including relaxing TLS relocations. Note that
+  // R_TPREL and R_TPREL_NEG relocations are resolved in processRelocAux.
+  if (expr == R_TPREL || expr == R_TPREL_NEG) {
+    if (config->shared) {
+      errorOrWarn("relocation " + toString(type) + " against " + toString(sym) +
+                  " cannot be used with -shared" +
+                  getLocation(sec, sym, offset));
+      return;
+    }
+  } else if (unsigned processed = handleTlsRelocation<ELFT>(
+                 type, sym, sec, offset, addend, expr)) {
     i += (processed - 1);
     return;
   }

diff  --git a/lld/test/ELF/Inputs/i386-static-tls-model4.s b/lld/test/ELF/Inputs/i386-static-tls-model4.s
deleted file mode 100644
index 6006518bfd7c..000000000000
--- a/lld/test/ELF/Inputs/i386-static-tls-model4.s
+++ /dev/null
@@ -1,9 +0,0 @@
-.section ".tdata", "awT", @progbits
-.globl var
-var:
-
-.section .foo, "aw"
-.global _start
-_start:
- movl %gs:0, %eax
- leal var at ntpoff(%eax), %eax # R_386_TLS_LE

diff  --git a/lld/test/ELF/aarch64-tls-le.s b/lld/test/ELF/aarch64-tls-le.s
index e63a379fcc45..c43345e8e254 100644
--- a/lld/test/ELF/aarch64-tls-le.s
+++ b/lld/test/ELF/aarch64-tls-le.s
@@ -8,6 +8,14 @@
 #RELOC:      Relocations [
 #RELOC-NEXT: ]
 
+## Reject local-exec TLS relocations for -shared.
+# RUN: not ld.lld -shared %tmain.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error:
+
+# ERR: error: relocation R_AARCH64_TLSLE_ADD_TPREL_HI12 against v1 cannot be used with -shared
+# ERR: error: relocation R_AARCH64_TLSLE_ADD_TPREL_LO12_NC against v1 cannot be used with -shared
+# ERR: error: relocation R_AARCH64_TLSLE_ADD_TPREL_HI12 against v2 cannot be used with -shared
+# ERR: error: relocation R_AARCH64_TLSLE_ADD_TPREL_LO12_NC against v2 cannot be used with -shared
+
 .globl _start
 _start:
  mrs x0, TPIDR_EL0

diff  --git a/lld/test/ELF/arm-tls-le32.s b/lld/test/ELF/arm-tls-le32.s
index 739752209db4..49469c2b6bfa 100644
--- a/lld/test/ELF/arm-tls-le32.s
+++ b/lld/test/ELF/arm-tls-le32.s
@@ -8,6 +8,13 @@
 /// statically for an application. The code sequences assume a thread pointer
 /// in r9
 
+/// Reject local-exec TLS relocations for -shared.
+// RUN: not ld.lld -shared %t.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error:
+
+// ERR: error: relocation R_ARM_TLS_LE32 against x cannot be used with -shared
+// ERR: error: relocation R_ARM_TLS_LE32 against y cannot be used with -shared
+// ERR: error: relocation R_ARM_TLS_LE32 against z cannot be used with -shared
+
  .text
  .syntax unified
  .globl  _start

diff  --git a/lld/test/ELF/i386-static-tls-model.s b/lld/test/ELF/i386-static-tls-model.s
index cfd7cf6ba972..dfbbed25ef22 100644
--- a/lld/test/ELF/i386-static-tls-model.s
+++ b/lld/test/ELF/i386-static-tls-model.s
@@ -1,9 +1,5 @@
 # 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
@@ -12,9 +8,5 @@
 # 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/lld/test/ELF/i386-tls-le.s b/lld/test/ELF/i386-tls-le.s
index b94ffbb67f07..bcb4a8e21abc 100644
--- a/lld/test/ELF/i386-tls-le.s
+++ b/lld/test/ELF/i386-tls-le.s
@@ -1,11 +1,19 @@
 # REQUIRES: x86
 # RUN: llvm-mc -filetype=obj -triple=i686 %s -o %t.o
 # RUN: ld.lld %t.o -o %t
-# RUN: ld.lld %t.o -shared -o %t.so
+# RUN: ld.lld %t.o -pie -o %t.pie
 # RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=DIS
 # RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=RELOC
-# RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck %s --check-prefix=DISSHARED
-# RUN: llvm-readobj -r %t.so | FileCheck %s --check-prefix=RELOCSHARED
+# RUN: llvm-objdump -d --no-show-raw-insn %t.pie | FileCheck %s --check-prefix=DIS
+# RUN: llvm-readobj -r %t.pie | FileCheck %s --check-prefix=RELOC
+
+## Reject local-exec TLS relocations for -shared.
+# RUN: not ld.lld -shared %t.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error:
+
+# ERR: error: relocation R_386_TLS_LE_32 against var cannot be used with -shared
+# ERR: error: relocation R_386_TLS_LE_32 against var1 cannot be used with -shared
+# ERR: error: relocation R_386_TLS_LE against var cannot be used with -shared
+# ERR: error: relocation R_386_TLS_LE against var1 cannot be used with -shared
 
 .section ".tdata", "awT", @progbits
 .globl var
@@ -33,39 +41,16 @@ _start:
 # DIS:      Disassembly of section test:
 # DIS-EMPTY:
 # DIS-NEXT: <_start>:
-# DIS-NEXT: 402134:       movl    $8, %edx
-# DIS-NEXT: 402139:       movl    %gs:0, %ecx
-# DIS-NEXT: 402140:       subl    %edx, %eax
-# DIS-NEXT: 402142:       movl    $4, %edx
-# DIS-NEXT: 402147:       movl    %gs:0, %ecx
-# DIS-NEXT: 40214e:       subl    %edx, %eax
-# DIS-NEXT: 402150:       movl    %gs:0, %ecx
-# DIS-NEXT: 402157:       leal    -8(%ecx), %eax
-# DIS-NEXT: 40215d:       movl    %gs:0, %ecx
-# DIS-NEXT: 402164:       leal    119(%ecx), %eax
+# DIS-NEXT:   movl    $8, %edx
+# DIS-NEXT:   movl    %gs:0, %ecx
+# DIS-NEXT:   subl    %edx, %eax
+# DIS-NEXT:   movl    $4, %edx
+# DIS-NEXT:   movl    %gs:0, %ecx
+# DIS-NEXT:   subl    %edx, %eax
+# DIS-NEXT:   movl    %gs:0, %ecx
+# DIS-NEXT:   leal    -8(%ecx), %eax
+# DIS-NEXT:   movl    %gs:0, %ecx
+# DIS-NEXT:   leal    119(%ecx), %eax
 
 # RELOC: Relocations [
 # RELOC-NEXT: ]
-
-# DISSHARED: Disassembly of section test:
-# DISSHARED-EMPTY:
-# DISSHARED-NEXT: <_start>:
-# DISSHARED-NEXT: 2218:       movl    $0, %edx
-# DISSHARED-NEXT: 221d:       movl    %gs:0, %ecx
-# DISSHARED-NEXT: 2224:       subl    %edx, %eax
-# DISSHARED-NEXT: 2226:       movl    $0, %edx
-# DISSHARED-NEXT: 222b:       movl    %gs:0, %ecx
-# DISSHARED-NEXT: 2232:       subl    %edx, %eax
-# DISSHARED-NEXT: 2234:       movl    %gs:0, %ecx
-# DISSHARED-NEXT: 223b:       leal    (%ecx), %eax
-# DISSHARED-NEXT: 2241:       movl    %gs:0, %ecx
-# DISSHARED-NEXT: 2248:       leal    123(%ecx), %eax
-
-# RELOCSHARED:      Relocations [
-# RELOCSHARED-NEXT: Section (5) .rel.dyn {
-# RELOCSHARED-NEXT:   0x2219 R_386_TLS_TPOFF32 var
-# RELOCSHARED-NEXT:   0x223D R_386_TLS_TPOFF var
-# RELOCSHARED-NEXT:   0x2227 R_386_TLS_TPOFF32 var1
-# RELOCSHARED-NEXT:   0x224A R_386_TLS_TPOFF var1
-# RELOCSHARED-NEXT:  }
-# RELOCSHARED-NEXT: ]

diff  --git a/lld/test/ELF/i386-zrel-zrela.s b/lld/test/ELF/i386-zrel-zrela.s
index 27ff3bcab9a5..5e73ca203524 100644
--- a/lld/test/ELF/i386-zrel-zrela.s
+++ b/lld/test/ELF/i386-zrel-zrela.s
@@ -27,7 +27,7 @@
 # REL-NEXT: }
 
 # REL:      Hex dump of section '.data':
-# REL-NEXT: 0x000042cc cc420000 2a000000
+# REL-NEXT: 0x000042d0 d0420000 2a000000
 
 # RUN: ld.lld -shared -z rel -z rela %t.o -o %t2.so
 # RUN: llvm-readobj -d -r %t2.so | FileCheck --check-prefix=RELA %s
@@ -41,9 +41,9 @@
 # RELA-NEXT: PLTGOT    {{.*}}
 # RELA-NEXT: PLTREL    RELA
 # RELA:      .rela.dyn {
-# RELA-NEXT:   R_386_RELATIVE - 0x42EC
+# RELA-NEXT:   R_386_RELATIVE - 0x42F0
 # RELA-NEXT:   R_386_GLOB_DAT func 0x0
-# RELA-NEXT:   R_386_TLS_TPOFF tls 0x2A
+# RELA-NEXT:   R_386_TLS_TPOFF tls 0x0
 # RELA-NEXT:   R_386_32 _start 0x2A
 # RELA-NEXT: }
 # RELA-NEXT: .rela.plt {
@@ -56,7 +56,7 @@ _start:
   movl func at GOT(%eax), %eax
 
 .section .text1,"awx"
-  movl %gs:tls at NTPOFF+42, %eax
+  movl tls at GOTNTPOFF(%eax), %eax
 
 .data
   .long .data

diff  --git a/lld/test/ELF/mips-tls-hilo.s b/lld/test/ELF/mips-tls-hilo.s
index 4f1417d29525..92cf71be5ecc 100644
--- a/lld/test/ELF/mips-tls-hilo.s
+++ b/lld/test/ELF/mips-tls-hilo.s
@@ -7,8 +7,10 @@
 # RUN: llvm-objdump -d -t --no-show-raw-insn %t.exe | FileCheck --check-prefix=DIS %s
 # RUN: llvm-readobj -r -A %t.exe | FileCheck %s
 
-# RUN: ld.lld %t.o -shared -o %t.so
-# RUN: llvm-readobj -r -A %t.so | FileCheck -check-prefix=SO %s
+# RUN: not ld.lld %t.o -shared -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error:
+
+# ERR: error: relocation R_MIPS_TLS_TPREL_HI16 against loc0 cannot be used with -shared
+# ERR: error: relocation R_MIPS_TLS_TPREL_LO16 against loc0 cannot be used with -shared
 
 # DIS: 00000000 l    O .tdata          00000000 loc0
 

diff  --git a/lld/test/ELF/ppc64-local-exec-tls.s b/lld/test/ELF/ppc64-local-exec-tls.s
index f657d96ad1f1..51dcb1a7395a 100644
--- a/lld/test/ELF/ppc64-local-exec-tls.s
+++ b/lld/test/ELF/ppc64-local-exec-tls.s
@@ -4,6 +4,18 @@
 // RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s
 // RUN: llvm-objdump -d %t | FileCheck --check-prefix=Dis %s
 
+// RUN: not ld.lld -shared %t.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR
+
+/// Reject local-exec TLS relocations for -shared.
+// ERR: error: relocation R_PPC64_TPREL16_HA against a cannot be used with -shared
+// ERR: error: relocation R_PPC64_TPREL16_LO against a cannot be used with -shared
+// ERR: error: relocation R_PPC64_TPREL16 against b cannot be used with -shared
+// ERR: error: relocation R_PPC64_TPREL16_HI against b cannot be used with -shared
+// ERR: error: relocation R_PPC64_TPREL16_DS against b cannot be used with -shared
+// ERR: error: relocation R_PPC64_TPREL16_LO_DS against b cannot be used with -shared
+// ERR: error: relocation R_PPC64_TPREL16_HIGHESTA against b cannot be used with -shared
+// ERR: error: relocation R_PPC64_TPREL16_HIGHERA against b cannot be used with -shared
+
 	.text
 	.abiversion 2
 	.globl	test_local_exec                    # -- Begin function test_local_exec

diff  --git a/lld/test/ELF/riscv-tls-le.s b/lld/test/ELF/riscv-tls-le.s
index 860e6884c5da..96a10e940218 100644
--- a/lld/test/ELF/riscv-tls-le.s
+++ b/lld/test/ELF/riscv-tls-le.s
@@ -13,6 +13,13 @@
 # RUN: ld.lld -pie %t.64.o -o %t.64
 # RUN: llvm-objdump -d --no-show-raw-insn %t.64 | FileCheck --check-prefixes=LE %s
 
+# RUN: not ld.lld -shared %t.32.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR --implicit-check-not=error:
+
+# ERR: error: relocation R_RISCV_TPREL_HI20 against .LANCHOR0 cannot be used with -shared
+# ERR: error: relocation R_RISCV_TPREL_LO12_I against .LANCHOR0 cannot be used with -shared
+# ERR: error: relocation R_RISCV_TPREL_HI20 against a cannot be used with -shared
+# ERR: error: relocation R_RISCV_TPREL_LO12_S against a cannot be used with -shared
+
 # NM: {{0*}}00000008 b .LANCHOR0
 # NM: {{0*}}0000000c B a
 

diff  --git a/lld/test/ELF/tls.s b/lld/test/ELF/tls.s
index 353a056ee20d..567e44600ab0 100644
--- a/lld/test/ELF/tls.s
+++ b/lld/test/ELF/tls.s
@@ -4,6 +4,26 @@
 // RUN: llvm-readobj -S -l --symbols %tout | FileCheck %s
 // RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DIS
 
+/// Reject local-exec TLS relocations for -shared, regardless of the preemptibility.
+// RUN: not ld.lld -shared %t -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR
+// RUN: not ld.lld -shared -Bsymbolic %t -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR
+
+// ERR:       error: relocation R_X86_64_TPOFF32 against a cannot be used with -shared
+// ERR-NEXT:  defined in {{.*}}
+// ERR-NEXT:  referenced by {{.*}}:(.text+0x4)
+// ERR-EMPTY:
+// ERR-NEXT:  error: relocation R_X86_64_TPOFF32 against b cannot be used with -shared
+// ERR-NEXT:  defined in {{.*}}
+// ERR-NEXT:  referenced by {{.*}}:(.text+0xC)
+// ERR-EMPTY:
+// ERR-NEXT:  error: relocation R_X86_64_TPOFF32 against c cannot be used with -shared
+// ERR-NEXT:  defined in {{.*}}
+// ERR-NEXT:  referenced by {{.*}}:(.text+0x14)
+// ERR-EMPTY:
+// ERR-NEXT:  error: relocation R_X86_64_TPOFF32 against d cannot be used with -shared
+// ERR-NEXT:  defined in {{.*}}
+// ERR-NEXT:  referenced by {{.*}}:(.text+0x1C)
+
 .global _start
 _start:
   movl %fs:a at tpoff, %eax

diff  --git a/lld/test/ELF/x86-64-reloc-tpoff32-fpic.s b/lld/test/ELF/x86-64-reloc-tpoff32-fpic.s
deleted file mode 100644
index edb04c1d4487..000000000000
--- a/lld/test/ELF/x86-64-reloc-tpoff32-fpic.s
+++ /dev/null
@@ -1,14 +0,0 @@
-# REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
-# RUN: not ld.lld %t.o -shared -o /dev/null 2>&1 | FileCheck %s
-
-# CHECK: relocation R_X86_64_TPOFF32 cannot be used against symbol var; recompile with -fPIC
-# CHECK: >>> defined in {{.*}}.o
-# CHECK: >>> referenced by {{.*}}.o:(.tdata+0xC)
-
-.section ".tdata", "awT", @progbits
-.globl var
-var:
-
-movq %fs:0, %rax
-leaq var at TPOFF(%rax),%rax


        


More information about the llvm-commits mailing list