Skip to content

Commit

Permalink
[ELF] Fix Initial-Exec TLS variables
Browse files Browse the repository at this point in the history
Previously, GOTTPOFF relocations against Initial-Exec TLS variables
got wrong value.

Fixes #197
  • Loading branch information
rui314 committed Dec 26, 2021
1 parent 888474b commit d116113
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 1 deletion.
5 changes: 4 additions & 1 deletion elf/output-chunks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -819,7 +819,7 @@ i64 GotSection<E>::get_reldyn_size(Context<E> &ctx) const {
n += tlsdesc_syms.size();

for (Symbol<E> *sym : gottp_syms)
if (sym->is_imported)
if (sym->is_imported || ctx.arg.shared)
n++;

if (tlsld_idx != -1)
Expand Down Expand Up @@ -869,6 +869,9 @@ void GotSection<E>::copy_buf(Context<E> &ctx) {
if (sym->is_imported) {
*rel++ = reloc<E>(sym->get_gottp_addr(ctx), E::R_TPOFF,
sym->get_dynsym_idx(ctx));
} else if (ctx.arg.shared) {
*rel++ = reloc<E>(sym->get_gottp_addr(ctx), E::R_TPOFF, 0,
sym->get_addr(ctx) - ctx.tls_begin);
} else if (E::e_machine == EM_386 || E::e_machine == EM_X86_64) {
buf[sym->get_gottp_idx(ctx)] = sym->get_addr(ctx) - ctx.tls_end;
} else {
Expand Down
60 changes: 60 additions & 0 deletions test/elf/tls-ie.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/bin/bash
export LANG=
set -e
cd $(dirname $0)
mold=`pwd`/../../mold
echo -n "Testing $(basename -s .sh $0) ... "
t=$(pwd)/../../out/test/elf/$(basename -s .sh $0)
mkdir -p $t

if [ $(uname -m) = x86_64 ]; then
dialect=gnu
elif [ $(uname -m) = aarch64 ]; then
dialect=trad
else
echo skipped
exit 0
fi

cat <<EOF | gcc -ftls-model=initial-exec -mtls-dialect=$dialect -fPIC -c -o $t/a.o -xc -
#include <stdio.h>
static _Thread_local int foo;
static _Thread_local int bar;
void set() {
foo = 3;
bar = 5;
}
void print() {
printf("%d %d ", foo, bar);
}
EOF

clang -fuse-ld=$mold -shared -o $t/b.so $t/a.o

cat <<EOF | gcc -c -o $t/c.o -xc -
#include <stdio.h>
_Thread_local int baz;
void set();
void print();
int main() {
baz = 7;
print();
set();
print();
printf("%d\n", baz);
}
EOF

clang -fuse-ld=$mold -o $t/exe $t/b.so $t/c.o
$t/exe | grep -q '^0 0 3 5 7$'

clang -fuse-ld=$mold -o $t/exe $t/b.so $t/c.o -Wl,-no-relax
$t/exe | grep -q '^0 0 3 5 7$'

echo OK

0 comments on commit d116113

Please sign in to comment.