summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2006-09-01 06:13:16 +0000
committermarcel <marcel@FreeBSD.org>2006-09-01 06:13:16 +0000
commita2087dd7518eff7fc29715db6db7a82162af672b (patch)
tree141de734840ef84ebd2ff541af68725b79186a51 /lib
parentdeb78746ab5940fcf2299c611c0a0013a4664bea (diff)
downloadFreeBSD-src-a2087dd7518eff7fc29715db6db7a82162af672b.zip
FreeBSD-src-a2087dd7518eff7fc29715db6db7a82162af672b.tar.gz
Fix the variant I allocation for KSE: Allow a larger TCB and assume
that the documented TCB is at the tail of the extended TCB. In other words, the base of the TCB has a negative offset from the TLS.
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/gen/tls.c83
1 files changed, 37 insertions, 46 deletions
diff --git a/lib/libc/gen/tls.c b/lib/libc/gen/tls.c
index 2d08a26..70de71b 100644
--- a/lib/libc/gen/tls.c
+++ b/lib/libc/gen/tls.c
@@ -58,7 +58,7 @@ void _rtld_free_tls(void *tls, size_t tcbsize, size_t tcbalign);
void *__libc_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign);
void __libc_free_tls(void *tls, size_t tcbsize, size_t tcbalign);
-#if defined(__ia64__) || defined(__alpha__) || defined(__powerpc__)
+#if defined(__ia64__) || defined(__powerpc__)
#define TLS_VARIANT_I
#endif
#if defined(__i386__) || defined(__amd64__) || defined(__sparc64__) || \
@@ -73,9 +73,6 @@ void __libc_free_tls(void *tls, size_t tcbsize, size_t tcbalign);
static size_t tls_static_space;
static size_t tls_init_size;
-#ifdef TLS_VARIANT_I
-static size_t tls_init_offset;
-#endif
static void *tls_init;
#endif
@@ -102,67 +99,69 @@ __libc_tls_get_addr(void *ti __unused)
#ifdef TLS_VARIANT_I
+#define TLS_TCB_SIZE (2 * sizeof(void *))
+
/*
* Free Static TLS using the Variant I method.
*/
void
-__libc_free_tls(void *tls, size_t tcbsize __unused, size_t tcbalign __unused)
+__libc_free_tls(void *tcb, size_t tcbsize, size_t tcbalign __unused)
{
- Elf_Addr* dtv;
+ Elf_Addr *dtv;
+ Elf_Addr **tls;
- dtv = ((Elf_Addr**)tls)[0];
- free(tls);
+ tls = (Elf_Addr **)((Elf_Addr)tcb + tcbsize - TLS_TCB_SIZE);
+ dtv = tls[0];
free(dtv);
+ free(tcb);
}
/*
* Allocate Static TLS using the Variant I method.
*/
void *
-__libc_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign __unused)
+__libc_allocate_tls(void *oldtcb, size_t tcbsize, size_t tcbalign __unused)
{
- size_t size;
- char *tls;
Elf_Addr *dtv;
+ Elf_Addr **tls;
+ char *tcb;
- size = tls_static_space;
- if (size < tcbsize)
- size = tcbsize;
-
- tls = calloc(1, size);
- dtv = malloc(3 * sizeof(Elf_Addr));
+ if (oldtcb != NULL && tcbsize == TLS_TCB_SIZE)
+ return (oldtcb);
- *(Elf_Addr **) tls = dtv;
+ tcb = calloc(1, tls_static_space + tcbsize);
+ tls = (Elf_Addr **)(tcb + tcbsize - TLS_TCB_SIZE);
- dtv[0] = 1;
- dtv[1] = 1;
- dtv[2] = (Elf_Addr)(tls + tls_init_offset);
- if (oldtls) {
- /*
- * Copy the static TLS block over whole.
- */
- memcpy(tls + tls_init_offset,
- (char *)oldtls + tls_init_offset,
- tls_static_space - tls_init_offset);
+ if (oldtcb != NULL) {
+ memcpy(tls, oldtcb, tls_static_space + TLS_TCB_SIZE);
+ free(oldtcb);
- /*
- * We assume that this block was the one we created with
- * allocate_initial_tls().
- */
- _rtld_free_tls(oldtls, 2 * sizeof(Elf_Addr), sizeof(Elf_Addr));
+ /* Adjust the DTV. */
+ dtv = tls[0];
+ dtv[2] = (Elf_Addr)tls + TLS_TCB_SIZE;
} else {
- memcpy(tls + tls_init_offset, tls_init, tls_init_size);
- memset(tls + tls_init_offset + tls_init_size,
- 0, tls_static_space - tls_init_size);
+ dtv = malloc(3 * sizeof(Elf_Addr));
+ tls[0] = dtv;
+ dtv[0] = 1;
+ dtv[1] = 1;
+ dtv[2] = (Elf_Addr)tls + TLS_TCB_SIZE;
+
+ if (tls_init_size > 0)
+ memcpy((void*)dtv[2], tls_init, tls_init_size);
+ if (tls_static_space > tls_init_size)
+ memset((void*)(dtv[2] + tls_init_size), 0,
+ tls_static_space - tls_init_size);
}
- return tls;
+ return(tcb);
}
#endif
#ifdef TLS_VARIANT_II
+#define TLS_TCB_SIZE (3 * sizeof(Elf_Addr))
+
/*
* Free Static TLS using the Variant II method.
*/
@@ -293,22 +292,14 @@ _init_tls()
for (i = 0; (unsigned) i < phnum; i++) {
if (phdr[i].p_type == PT_TLS) {
-#ifdef TLS_VARIANT_I
- tls_static_space = round(2*sizeof(Elf_Addr),
- phdr[i].p_align) + phdr[i].p_memsz;
- tls_init_offset = round(2*sizeof(Elf_Addr),
- phdr[i].p_align);
-#else
tls_static_space = round(phdr[i].p_memsz,
phdr[i].p_align);
-#endif
tls_init_size = phdr[i].p_filesz;
tls_init = (void*) phdr[i].p_vaddr;
}
}
- tls = _rtld_allocate_tls(NULL, 3*sizeof(Elf_Addr),
- sizeof(Elf_Addr));
+ tls = _rtld_allocate_tls(NULL, TLS_TCB_SIZE, 1);
_set_tp(tls);
#endif
OpenPOWER on IntegriCloud