Skip to content

Commit dc53d25

Browse files
committed
[X86] Fix R_X86_64_TPOFF32 against weak undefined TLS symbols
A weak undefined TLS symbol has no slot in the PT_TLS segment, so the thread-pointer-offset formula (S - templateSize) is meaningless for it. Previously relocTPOFF applied that formula with a bogus symbol value, producing an incorrect tpoff (e.g. -3) instead of the correct 0. Two fixes, mirroring lld's R_TPREL handling (if (sym.isUndefined()) return a): - relocTPOFF (x86_64Relocator.cpp): short-circuit weak undefined symbols in a static executable, returning the addend directly instead of running the tpoff formula. - finalizeTLSSymbol (GNULDBackend.cpp): return 0 (not 1/true) for symbols without a fragment reference, fixing the st_value written to .symtab for undefined TLS symbols. Add x86_64/linux/WeakUndefTLS covering TPOFF32/64 and DTPOFF32/64 against weak-undef symbols, a defined-symbol regression guard, and a non-zero addend case. Resolves #1540 Signed-off-by: Rachit Mehta <rachmeht@qti.qualcomm.com>
1 parent a30687e commit dc53d25

9 files changed

Lines changed: 110 additions & 4 deletions

File tree

lib/Target/GNULDBackend.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -759,11 +759,8 @@ uint64_t GNULDBackend::finalizeTLSSymbol(LDSymbol *pSymbol) {
759759
}
760760

761761
// ignore if symbol has no fragRef
762-
// FIXME: This is probably wrong. If a symbol does not have a fragment ref
763-
// that implies the symbol is undefined, in that case, the symbol index should
764-
// be 0 instead of 1 (true).
765762
if (!pSymbol->hasFragRef())
766-
return true;
763+
return false;
767764

768765
// the value of a TLS symbol is the offset to the TLS segment
769766
std::vector<ELFSegment *> tls_segs =

lib/Target/X86/x86_64Relocator.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,13 @@ Relocator::Result eld::relocTPOFF(Relocation &pReloc, x86_64Relocator &pParent,
752752

753753
uint64_t TLSTemplateSize = pParent.getTarget().getTLSTemplateSize();
754754

755+
ResolveInfo *rsym = pReloc.symInfo();
756+
if (rsym && rsym->isWeakUndef() &&
757+
(pParent.config().codeGenType() == LinkerConfig::Exec)) {
758+
Relocator::DWord A = pReloc.addend();
759+
return ApplyReloc(pReloc, A, pRelocDesc, DiagEngine, options, pParent);
760+
}
761+
755762
if (TLSTemplateSize == 0) {
756763
pParent.config().raise(Diag::no_pt_tls_segment);
757764
return Relocator::BadReloc;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.section .tdata, "awT", @progbits
2+
.align 4
3+
.global real_tls
4+
real_tls:
5+
.long 0
6+
7+
.section .data
8+
.align 4
9+
result:
10+
.long 0xdeadbeef
11+
.reloc result, R_X86_64_TPOFF32, real_tls
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.weak weak_tls
2+
.section .data
3+
.align 4
4+
result:
5+
.long 0xdeadbeef
6+
.reloc result, R_X86_64_DTPOFF32, weak_tls
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.weak weak_tls
2+
.section .data
3+
.align 8
4+
result:
5+
.quad 0xdeadbeefdeadbeef
6+
.reloc result, R_X86_64_DTPOFF64, weak_tls
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.weak weak_tls
2+
.section .data
3+
.align 4
4+
result:
5+
.long 0xdeadbeef
6+
.reloc result, R_X86_64_TPOFF32, weak_tls
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.weak weak_tls
2+
.section .data
3+
.align 8
4+
result:
5+
.quad 0xdeadbeefdeadbeef
6+
.reloc result, R_X86_64_TPOFF64, weak_tls
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.weak weak_tls
2+
.section .data
3+
.align 4
4+
result:
5+
.long 0xdeadbeef
6+
.reloc result, R_X86_64_TPOFF32, weak_tls+2
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#--WeakUndefTLS.test----------Executable--------#
2+
BEGIN_COMMENT
3+
# Test R_X86_64_TPOFF32/64 and R_X86_64_DTPOFF32/64 relocations against
4+
# weak undefined TLS symbols. A weak undefined TLS symbol has no TLS slot,
5+
# so the tpoff formula must not run; the result is the addend only (= 0
6+
# for the common case). Mirrors lld's R_TPREL guard:
7+
# if (sym.isUndefined()) return a;
8+
# Also verifies that defined TLS symbols are unaffected (regression guard).
9+
#END_COMMENT
10+
11+
#START_TEST
12+
13+
# Case 1: TPOFF32 + weak-undef -> 0x00000000
14+
RUN: %clang %clangopts -c %p/Inputs/weak_tls_le.s -o %t.le.o
15+
RUN: %link %linkopts -static %t.le.o -o %t.le.exe
16+
RUN: llvm-objdump -s -j .data %t.le.exe | FileCheck %s --check-prefix=LE32
17+
18+
# Case 2: TPOFF64 + weak-undef -> 0x0000000000000000
19+
RUN: %clang %clangopts -c %p/Inputs/weak_tls_le64.s -o %t.le64.o
20+
RUN: %link %linkopts -static %t.le64.o -o %t.le64.exe
21+
RUN: llvm-objdump -s -j .data %t.le64.exe | FileCheck %s --check-prefix=LE64
22+
23+
# Case 3: DTPOFF32 + weak-undef -> 0x00000000
24+
RUN: %clang %clangopts -c %p/Inputs/weak_tls_ld.s -o %t.ld.o
25+
RUN: %link %linkopts -static %t.ld.o -o %t.ld.exe
26+
RUN: llvm-objdump -s -j .data %t.ld.exe | FileCheck %s --check-prefix=LD32
27+
28+
# Case 4: DTPOFF64 + weak-undef -> 0x0000000000000000
29+
RUN: %clang %clangopts -c %p/Inputs/weak_tls_ld64.s -o %t.ld64.o
30+
RUN: %link %linkopts -static %t.ld64.o -o %t.ld64.exe
31+
RUN: llvm-objdump -s -j .data %t.ld64.exe | FileCheck %s --check-prefix=LD64
32+
33+
# Case 5: TPOFF32 + defined symbol -> -4 = 0xfffffffc (regression guard)
34+
RUN: %clang %clangopts -c %p/Inputs/weak_tls_defined.s -o %t.def.o
35+
RUN: %link %linkopts -static %t.def.o -o %t.def.exe
36+
RUN: llvm-objdump -s -j .data %t.def.exe | FileCheck %s --check-prefix=DEFINED
37+
38+
# Case 6: TPOFF32 + weak-undef + addend=2 -> 0x00000002
39+
RUN: %clang %clangopts -c %p/Inputs/weak_tls_le_addend.s -o %t.addend.o
40+
RUN: %link %linkopts -static %t.addend.o -o %t.addend.exe
41+
RUN: llvm-objdump -s -j .data %t.addend.exe | FileCheck %s --check-prefix=ADDEND
42+
43+
LE32: Contents of section .data:
44+
LE32-NEXT: {{[0-9a-f]+}} 00000000
45+
46+
LE64: Contents of section .data:
47+
LE64-NEXT: {{[0-9a-f]+}} 00000000 00000000
48+
49+
LD32: Contents of section .data:
50+
LD32-NEXT: {{[0-9a-f]+}} 00000000
51+
52+
LD64: Contents of section .data:
53+
LD64-NEXT: {{[0-9a-f]+}} 00000000 00000000
54+
55+
DEFINED: Contents of section .data:
56+
DEFINED-NEXT: {{[0-9a-f]+}} fcffffff
57+
58+
ADDEND: Contents of section .data:
59+
ADDEND-NEXT: {{[0-9a-f]+}} 02000000
60+
61+
#END_TEST

0 commit comments

Comments
 (0)