[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
This commit is contained in:
Fangrui Song 2020-12-21 08:47:04 -08:00
parent e25afcfa51
commit fb3c1b3de5
12 changed files with 94 additions and 77 deletions

View File

@ -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;
}

View File

@ -1,9 +0,0 @@
.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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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: ]

View File

@ -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@GOT(%eax), %eax
.section .text1,"awx"
movl %gs:tls@NTPOFF+42, %eax
movl tls@GOTNTPOFF(%eax), %eax
.data
.long .data

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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@tpoff, %eax

View File

@ -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@TPOFF(%rax),%rax