misc/160721: TLS is inconsistent
Thinker K.F. Li
thinker at codemud.net
Wed Sep 14 02:10:11 UTC 2011
>Number: 160721
>Category: misc
>Synopsis: TLS is inconsistent
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Wed Sep 14 02:10:10 UTC 2011
>Closed-Date:
>Last-Modified:
>Originator: Thinker K.F. Li
>Release: FreeBSD 9.0-CURRENT i386
>Organization:
Allwitz Tech.
>Environment:
System: FreeBSD eeebox.branda.to 9.0-CURRENT FreeBSD 9.0-CURRENT #1: Sun Jun 5 17:08:32 CST 2011 thinker at eeebox.branda.to:/usr/src/sys/i386/compile/eeebox i386
>Description:
Compiler generated code will call ___tls_get_addr() of ld-elf.so
for TLS variable. It is supposed to return the same address, every time,
for the same passed address and thread, but it does not.
>How-To-Repeat:
Compile following code with commands
1. cc -shared -o test-tls-1.so -pthread -fpic test-tls-1.c
2. cc -o test-tls -pthread test-tls.c
test-tls is supposed to print "100" on stdout, but it print out "50",
instead. If you dig into opcodes, you will find that ___tls_get_addr()
return two different base addresses for modify() and for show() respective.
This issue is only making troubles for programs accessing TLS after dlopen().
--- test-tls-1.c begins here ---
#include <stdio.h>
__thread int var = 50;
void
modify(void) {
var = 100;
}
void
show(void) {
printf("%d\n", var);
}
--- test-tls-1.c ends here ---
--- test-tls.c begins here ---
#include <stdio.h>
#include <dlfcn.h>
int
main(int argc, char * const *argv) {
void (*modify)(void);
void (*modify)(void);
void *sohdl;
sohdl = dlopen("./test-tls-1.so", RTLD_NOW);
modify = (void (*)(void))dlsym(sohdl, "modify");
show = (void (*)(void))dlsym(sohdl, "show");
modify();
show();
return 0;
}
--- test-tls.c ends here ---
>Fix:
Apply following patch on the root of source tree can fix this issue.
--- libexec-rtld_elf-rtld.c.diff begins here ---
--- libexec/rtld-elf/rtld.c.orig 2011-09-13 14:25:17.000000000 +0800
+++ libexec/rtld-elf/rtld.c 2011-09-13 14:25:43.000000000 +0800
@@ -3371,6 +3371,7 @@
free(dtv);
lock_release(rtld_bind_lock, &lockstate);
*dtvp = newdtv;
+ dtv = newdtv;
}
/* Dynamically allocate module TLS if necessary */
--- libexec-rtld_elf-rtld.c.diff ends here ---
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list