Skip to content

Commit

Permalink
[ELF] -r: don't define _TLS_MODULE_BASE_
Browse files Browse the repository at this point in the history
_TLS_MODULE_BASE_ is supposed to be defined by the final link. Defining it in a
relocatable link may render the final link value incorrect.

GNU ld i386/x86-64 have the same issue: https://sourceware.org/bugzilla/show_bug.cgi?id=29820
  • Loading branch information
MaskRay committed Nov 22, 2022
1 parent 2ec79af commit 8610cb0
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 19 deletions.
38 changes: 19 additions & 19 deletions lld/ELF/Writer.cpp
Expand Up @@ -1862,26 +1862,26 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
addOptionalRegular("__global_pointer$", sec ? sec : Out::elfHeader, 0x800,
STV_DEFAULT);
}
}

if (config->emachine == EM_386 || config->emachine == EM_X86_64) {
// On targets that support TLSDESC, _TLS_MODULE_BASE_ is defined in such a
// way that:
//
// 1) Without relaxation: it produces a dynamic TLSDESC relocation that
// computes 0.
// 2) With LD->LE relaxation: _TLS_MODULE_BASE_@tpoff = 0 (lowest address in
// the TLS block).
//
// 2) is special cased in @tpoff computation. To satisfy 1), we define it as
// an absolute symbol of zero. This is different from GNU linkers which
// define _TLS_MODULE_BASE_ relative to the first TLS section.
Symbol *s = symtab.find("_TLS_MODULE_BASE_");
if (s && s->isUndefined()) {
s->resolve(Defined{/*file=*/nullptr, StringRef(), STB_GLOBAL, STV_HIDDEN,
STT_TLS, /*value=*/0, 0,
/*section=*/nullptr});
ElfSym::tlsModuleBase = cast<Defined>(s);
if (config->emachine == EM_386 || config->emachine == EM_X86_64) {
// On targets that support TLSDESC, _TLS_MODULE_BASE_ is defined in such a
// way that:
//
// 1) Without relaxation: it produces a dynamic TLSDESC relocation that
// computes 0.
// 2) With LD->LE relaxation: _TLS_MODULE_BASE_@tpoff = 0 (lowest address
// in the TLS block).
//
// 2) is special cased in @tpoff computation. To satisfy 1), we define it
// as an absolute symbol of zero. This is different from GNU linkers which
// define _TLS_MODULE_BASE_ relative to the first TLS section.
Symbol *s = symtab.find("_TLS_MODULE_BASE_");
if (s && s->isUndefined()) {
s->resolve(Defined{/*file=*/nullptr, StringRef(), STB_GLOBAL,
STV_HIDDEN, STT_TLS, /*value=*/0, 0,
/*section=*/nullptr});
ElfSym::tlsModuleBase = cast<Defined>(s);
}
}
}

Expand Down
8 changes: 8 additions & 0 deletions lld/test/ELF/x86-64-tlsdesc-ld.s
Expand Up @@ -32,6 +32,14 @@
# LE-NEXT: movl %fs:-8(%rax), %edx
# LE-NEXT: addl %fs:-4(%rax), %edx

# RUN: ld.lld -r %t.o -o %t.ro
# RUN: llvm-readelf -s %t.ro | FileCheck --check-prefix=RELOCATABLE %s
# RUN: ld.lld %t.ro -o %t
# RUN: llvm-readelf -r %t | FileCheck --check-prefix=NOREL %s
# RUN: llvm-objdump --no-print-imm-hex -d --no-show-raw-insn %t | FileCheck --check-prefix=LE %s

# RELOCATABLE: 0000000000000000 0 TLS GLOBAL DEFAULT UND _TLS_MODULE_BASE_

leaq _TLS_MODULE_BASE_@tlsdesc(%rip), %rax
call *_TLS_MODULE_BASE_@tlscall(%rax)
movl %fs:a@dtpoff(%rax), %edx
Expand Down

0 comments on commit 8610cb0

Please sign in to comment.