-
-
Notifications
You must be signed in to change notification settings - Fork 464
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ELF] Align the first TLS section with largest required TLS alignment.
TLS chunks alignments are special: in addition to having their virtual addresses aligned, they also have to be aligned when the region of tls_begin is copied to a new thread's storage area. In other words, their offset against tls_begin also has to be aligned. A good way to achieve this is to take the largest alignment requirement of all TLS sections and make tls_begin also aligned to that. Signed-off-by: Tatsuyuki Ishi <ishitatsuyuki@gmail.com>
- Loading branch information
1 parent
48b2c0f
commit bd46edf
Showing
2 changed files
with
75 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
#!/bin/bash | ||
. $(dirname $0)/common.inc | ||
|
||
# Test a tricky case of TLS alignment requirement where not only the virtual | ||
# address of a symbol but also its offset against the TLS base address has to | ||
# be aligned. | ||
# | ||
# On glibc, this issue requires a TLS model equivalent to global-dynamic in | ||
# order to be triggered. | ||
|
||
cat <<EOF | $CC -fPIC -c -o $t/a.o -xc - | ||
#include <assert.h> | ||
#include <stdlib.h> | ||
// .tdata | ||
_Thread_local int x = 42; | ||
// .tbss | ||
__attribute__ ((aligned(64))) | ||
_Thread_local int y = 0; | ||
void *verify(void *unused) { | ||
assert((unsigned long)(&y) % 64 == 0); | ||
return NULL; | ||
} | ||
EOF | ||
|
||
cat <<EOF | $CC -fPIC -c -o $t/b.o -xc - | ||
#include <pthread.h> | ||
#include <dlfcn.h> | ||
#include <assert.h> | ||
void *(*verify)(void *); | ||
int main() { | ||
void *handle = dlopen("a.so", RTLD_NOW); | ||
assert(handle); | ||
*(void**)(&verify) = dlsym(handle, "verify"); | ||
assert(verify); | ||
pthread_t thread; | ||
verify(NULL); | ||
pthread_create(&thread, NULL, verify, NULL); | ||
pthread_join(thread, NULL); | ||
} | ||
EOF | ||
|
||
$CC -B. -shared -o $t/a.so $t/a.o | ||
$CC -B. -ldl -pthread -o $t/exe $t/b.o -Wl,-rpath,$t | ||
$QEMU $t/exe |