summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordfr <dfr@FreeBSD.org>2004-08-15 16:18:52 +0000
committerdfr <dfr@FreeBSD.org>2004-08-15 16:18:52 +0000
commit2f90ca8b3cce7d9b8e36a7641f90e8d59ebde4a5 (patch)
treee8c5fbe955b31ea20466f96e5959370ad849667b
parentce4e47fed011aaea8720c16b940600231fdab789 (diff)
downloadFreeBSD-src-2f90ca8b3cce7d9b8e36a7641f90e8d59ebde4a5.zip
FreeBSD-src-2f90ca8b3cce7d9b8e36a7641f90e8d59ebde4a5.tar.gz
Add support for TLS in statically linked programs.
-rw-r--r--lib/csu/alpha/crt1.c2
-rw-r--r--lib/csu/amd64/crt1.c2
-rw-r--r--lib/csu/arm/crt1.c2
-rw-r--r--lib/csu/i386-elf/crt1.c2
-rw-r--r--lib/csu/ia64/crt1.S5
-rw-r--r--lib/csu/powerpc/crt1.c2
-rw-r--r--lib/csu/sparc64/crt1.c2
-rw-r--r--lib/libc/alpha/gen/Makefile.inc2
-rw-r--r--lib/libc/alpha/gen/_set_tp.c37
-rw-r--r--lib/libc/amd64/gen/Makefile.inc2
-rw-r--r--lib/libc/amd64/gen/_set_tp.c38
-rw-r--r--lib/libc/gen/tls.c227
-rw-r--r--lib/libc/i386/gen/Makefile.inc2
-rw-r--r--lib/libc/i386/gen/_set_tp.c52
-rw-r--r--lib/libc/ia64/gen/Makefile.inc2
-rw-r--r--lib/libc/ia64/gen/_set_tp.c35
-rw-r--r--lib/libc/include/libc_private.h9
-rw-r--r--lib/libc/powerpc/gen/Makefile.inc3
-rw-r--r--lib/libc/powerpc/gen/_set_tp.c35
-rw-r--r--lib/libc/sparc64/gen/Makefile.inc2
-rw-r--r--lib/libc/sparc64/gen/_set_tp.c35
21 files changed, 490 insertions, 8 deletions
diff --git a/lib/csu/alpha/crt1.c b/lib/csu/alpha/crt1.c
index b8ad3ea..7a936e9 100644
--- a/lib/csu/alpha/crt1.c
+++ b/lib/csu/alpha/crt1.c
@@ -93,6 +93,8 @@ _start(char **ap, void (*cleanup)(void), struct Struct_Obj_Entry *obj __unused,
if (&_DYNAMIC != NULL)
atexit(cleanup);
+ else
+ _init_tls();
#ifdef GCRT
atexit(_mcleanup);
diff --git a/lib/csu/amd64/crt1.c b/lib/csu/amd64/crt1.c
index 15aec44..f1f0f7b 100644
--- a/lib/csu/amd64/crt1.c
+++ b/lib/csu/amd64/crt1.c
@@ -77,6 +77,8 @@ _start(char **ap, void (*cleanup)(void))
if (&_DYNAMIC != NULL)
atexit(cleanup);
+ else
+ _init_tls();
#ifdef GCRT
atexit(_mcleanup);
diff --git a/lib/csu/arm/crt1.c b/lib/csu/arm/crt1.c
index 706aaee..bcee2ca 100644
--- a/lib/csu/arm/crt1.c
+++ b/lib/csu/arm/crt1.c
@@ -116,6 +116,8 @@ __start(int argc, char **argv, char **env,
if (&_DYNAMIC != NULL)
atexit(cleanup);
+ else
+ _init_tls();
#ifdef GCRT
atexit(_mcleanup);
diff --git a/lib/csu/i386-elf/crt1.c b/lib/csu/i386-elf/crt1.c
index 15a544c..9e8acaa 100644
--- a/lib/csu/i386-elf/crt1.c
+++ b/lib/csu/i386-elf/crt1.c
@@ -92,6 +92,8 @@ _start(char *ap, ...)
if (&_DYNAMIC != NULL)
atexit(cleanup);
+ else
+ _init_tls();
#ifdef GCRT
atexit(_mcleanup);
diff --git a/lib/csu/ia64/crt1.S b/lib/csu/ia64/crt1.S
index 9d6fb53..8740299 100644
--- a/lib/csu/ia64/crt1.S
+++ b/lib/csu/ia64/crt1.S
@@ -107,6 +107,11 @@ _start:
(p7) br.call.sptk b0=atexit
;;
}
+{ .mfb
+ nop 0
+ nop 0
+ br.call.sptk b0=_init_tls
+}
#ifdef GCRT
{ .mmi
mov gp=GP
diff --git a/lib/csu/powerpc/crt1.c b/lib/csu/powerpc/crt1.c
index 4c98271..080691c 100644
--- a/lib/csu/powerpc/crt1.c
+++ b/lib/csu/powerpc/crt1.c
@@ -100,6 +100,8 @@ _start(int argc, char **argv, char **env,
if (&_DYNAMIC != NULL)
atexit(cleanup);
+ else
+ _init_tls();
#ifdef GCRT
atexit(_mcleanup);
diff --git a/lib/csu/sparc64/crt1.c b/lib/csu/sparc64/crt1.c
index 9930830..19c0fad 100644
--- a/lib/csu/sparc64/crt1.c
+++ b/lib/csu/sparc64/crt1.c
@@ -102,6 +102,8 @@ _start(char **ap, void (*cleanup)(void), struct Struct_Obj_Entry *obj __unused,
if (&_DYNAMIC != NULL)
atexit(cleanup);
+ else
+ _init_tls();
#ifdef GCRT
atexit(_mcleanup);
diff --git a/lib/libc/alpha/gen/Makefile.inc b/lib/libc/alpha/gen/Makefile.inc
index 8f69274..96a92ce 100644
--- a/lib/libc/alpha/gen/Makefile.inc
+++ b/lib/libc/alpha/gen/Makefile.inc
@@ -1,6 +1,6 @@
# $FreeBSD$
-SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c setjmp.S
+SRCS+= _setjmp.S _set_tp.c fabs.S infinity.c ldexp.c modf.c setjmp.S
SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
fpsetround.c fpsetsticky.c
diff --git a/lib/libc/alpha/gen/_set_tp.c b/lib/libc/alpha/gen/_set_tp.c
new file mode 100644
index 0000000..e100d7b
--- /dev/null
+++ b/lib/libc/alpha/gen/_set_tp.c
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2004 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdint.h>
+#include <machine/alpha_cpu.h>
+
+void
+_set_tp(void *tp)
+{
+
+ alpha_pal_wrunique((uintptr_t) tp);
+}
diff --git a/lib/libc/amd64/gen/Makefile.inc b/lib/libc/amd64/gen/Makefile.inc
index 9cae7fa..3d28e66 100644
--- a/lib/libc/amd64/gen/Makefile.inc
+++ b/lib/libc/amd64/gen/Makefile.inc
@@ -1,7 +1,7 @@
# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
# $FreeBSD$
-SRCS+= _setjmp.S rfork_thread.S setjmp.S sigsetjmp.S \
+SRCS+= _setjmp.S _set_tp.c rfork_thread.S setjmp.S sigsetjmp.S \
fabs.S modf.S \
infinity.c ldexp.c makecontext.c signalcontext.c \
flt_rounds.c fpgetmask.c fpsetmask.c fpgetprec.c fpsetprec.c \
diff --git a/lib/libc/amd64/gen/_set_tp.c b/lib/libc/amd64/gen/_set_tp.c
new file mode 100644
index 0000000..02e5e14
--- /dev/null
+++ b/lib/libc/amd64/gen/_set_tp.c
@@ -0,0 +1,38 @@
+/*-
+ * Copyright (c) 2004 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <string.h>
+#include <stdint.h>
+#include <machine/sysarch.h>
+
+void
+_set_tp(void *tp)
+{
+
+ amd64_set_fsbase(tp);
+}
diff --git a/lib/libc/gen/tls.c b/lib/libc/gen/tls.c
index 1c4f8ce..59e44b7 100644
--- a/lib/libc/gen/tls.c
+++ b/lib/libc/gen/tls.c
@@ -32,7 +32,35 @@
* runtime from ld-elf.so.1.
*/
-#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <elf.h>
+#include <assert.h>
+#include "libc_private.h"
+
+/* XXX not sure what variants to use for arm. */
+
+#if defined(__ia64__) || defined(__alpha__) || defined(__powerpc__)
+#define TLS_VARIANT_I
+#endif
+#if defined(__i386__) || defined(__amd64__) || defined(__sparc64__)
+#define TLS_VARIANT_II
+#endif
+
+#ifndef PIC
+
+#define round(size, align) \
+ (((size) + (align) - 1) & ~((align) - 1))
+
+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;
+
+void _rtld_free_tls(void *tcb, size_t tcbsize, size_t tcbalign);
+#endif
#ifdef __i386__
@@ -55,15 +83,210 @@ __tls_get_addr()
return (0);
}
-#pragma weak _rtld_allocate_tls
+#ifdef TLS_VARIANT_I
+
+void
+_rtld_free_tls(void *tls, size_t tcbsize, size_t tcbalign)
+{
+#ifndef PIC
+ Elf_Addr* dtv;
+
+ dtv = ((Elf_Addr**)tls)[0];
+ free(tls);
+ free(dtv);
+#endif
+}
+
+/*
+ * Allocate Static TLS using the Variant I method.
+ */
void *
_rtld_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign)
{
+#ifndef PIC
+ size_t size;
+ char *tls;
+ Elf_Addr *dtv;
+
+ size = tls_static_space;
+
+ tls = malloc(size);
+ dtv = malloc(3 * sizeof(Elf_Addr));
+
+ *(Elf_Addr**) tls = dtv;
+
+ 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);
+
+ /*
+ * 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));
+ } 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);
+ }
+
+ return tls;
+#else
return (0);
+#endif
}
+#endif
+
+#ifdef TLS_VARIANT_II
+
+/*
+ * Free Static TLS using the Variant II method.
+ */
#pragma weak _rtld_free_tls
void
_rtld_free_tls(void *tcb, size_t tcbsize, size_t tcbalign)
{
+#ifndef PIC
+ size_t size;
+ Elf_Addr* dtv;
+ Elf_Addr tlsstart, tlsend;
+
+ /*
+ * Figure out the size of the initial TLS block so that we can
+ * find stuff which ___tls_get_addr() allocated dynamically.
+ */
+ size = round(tls_static_space, tcbalign);
+
+ dtv = ((Elf_Addr**)tcb)[1];
+ tlsend = (Elf_Addr) tcb;
+ tlsstart = tlsend - size;
+ free((void*) tlsstart);
+ free(dtv);
+#endif
+}
+
+#pragma weak _rtld_allocate_tls
+/*
+ * Allocate Static TLS using the Variant II method.
+ */
+void *
+_rtld_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign)
+{
+#ifndef PIC
+ size_t size;
+ char *tls;
+ Elf_Addr *dtv;
+ Elf_Addr segbase, oldsegbase;
+
+ size = round(tls_static_space, tcbalign);
+
+ assert(tcbsize >= 2*sizeof(Elf_Addr));
+ tls = malloc(size + tcbsize);
+ dtv = malloc(3 * sizeof(Elf_Addr));
+
+ segbase = (Elf_Addr)(tls + size);
+ ((Elf_Addr*)segbase)[0] = segbase;
+ ((Elf_Addr*)segbase)[1] = (Elf_Addr) dtv;
+
+ dtv[0] = 1;
+ dtv[1] = 1;
+ dtv[2] = segbase - tls_static_space;
+
+ if (oldtls) {
+ /*
+ * Copy the static TLS block over whole.
+ */
+ oldsegbase = (Elf_Addr) oldtls;
+ memcpy((void *)(segbase - tls_static_space),
+ (const void *)(oldsegbase - tls_static_space),
+ tls_static_space);
+
+ /*
+ * 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));
+ } else {
+ memcpy((void *)(segbase - tls_static_space),
+ tls_init, tls_init_size);
+ memset((void *)(segbase - tls_static_space + tls_init_size),
+ 0, tls_static_space - tls_init_size);
+ }
+
+ return (void*) segbase;
+#else
+ return (0);
+#endif
+}
+
+#endif
+
+void
+_init_tls()
+{
+#ifndef PIC
+ extern char **environ;
+ Elf_Addr *sp;
+ Elf_Auxinfo *aux, *auxp;
+ Elf_Phdr *phdr;
+ size_t phent, phnum;
+ int i;
+
+ sp = (Elf_Addr *) environ;
+ while (*sp++ != 0)
+ ;
+ aux = (Elf_Auxinfo *) sp;
+ phdr = 0;
+ phent = phnum = 0;
+ for (auxp = aux; auxp->a_type != AT_NULL; auxp++) {
+ switch (auxp->a_type) {
+ case AT_PHDR:
+ phdr = auxp->a_un.a_ptr;
+ break;
+
+ case AT_PHENT:
+ phent = auxp->a_un.a_val;
+ break;
+
+ case AT_PHNUM:
+ phnum = auxp->a_un.a_val;
+ break;
+ }
+ }
+ if (phdr == 0 || phent != sizeof(Elf_Phdr) || phnum == 0)
+ return;
+
+ for (i = 0; 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;
+ }
+ }
+
+ if (tls_static_space > 0) {
+ void* tls;
+
+ tls = _rtld_allocate_tls(NULL, 2*sizeof(Elf_Addr),
+ sizeof(Elf_Addr));
+
+ _set_tp(tls);
+ }
+#endif
}
diff --git a/lib/libc/i386/gen/Makefile.inc b/lib/libc/i386/gen/Makefile.inc
index 7776387..709cf5d 100644
--- a/lib/libc/i386/gen/Makefile.inc
+++ b/lib/libc/i386/gen/Makefile.inc
@@ -1,6 +1,6 @@
# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
# $FreeBSD$
-SRCS+= _ctx_start.S _setjmp.S alloca.S fabs.S \
+SRCS+= _ctx_start.S _setjmp.S _set_tp.c alloca.S fabs.S \
flt_rounds.c infinity.c ldexp.c makecontext.c modf.S \
rfork_thread.S setjmp.S signalcontext.c sigsetjmp.S
diff --git a/lib/libc/i386/gen/_set_tp.c b/lib/libc/i386/gen/_set_tp.c
new file mode 100644
index 0000000..d975b79
--- /dev/null
+++ b/lib/libc/i386/gen/_set_tp.c
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2004 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <string.h>
+#include <stdint.h>
+#include <machine/segments.h>
+#include <machine/sysarch.h>
+
+void
+_set_tp(void *tp)
+{
+ union descriptor ldt;
+ int sel;
+
+ memset(&ldt, 0, sizeof(ldt));
+ ldt.sd.sd_lolimit = 0xffff; /* 4G limit */
+ ldt.sd.sd_lobase = ((uintptr_t)tp) & 0xffffff;
+ ldt.sd.sd_type = SDT_MEMRWA;
+ ldt.sd.sd_dpl = SEL_UPL;
+ ldt.sd.sd_p = 1; /* present */
+ ldt.sd.sd_hilimit = 0xf; /* 4G limit */
+ ldt.sd.sd_def32 = 1; /* 32 bit */
+ ldt.sd.sd_gran = 1; /* limit in pages */
+ ldt.sd.sd_hibase = (((uintptr_t)tp) >> 24) & 0xff;
+ sel = i386_set_ldt(LDT_AUTO_ALLOC, &ldt, 1);
+ __asm __volatile("movl %0,%%gs" : : "rm" ((sel << 3) | 7));
+}
diff --git a/lib/libc/ia64/gen/Makefile.inc b/lib/libc/ia64/gen/Makefile.inc
index f7dcd6a..1eb7264 100644
--- a/lib/libc/ia64/gen/Makefile.inc
+++ b/lib/libc/ia64/gen/Makefile.inc
@@ -2,7 +2,7 @@
SRCS+= __divdf3.S __divdi3.S __divsf3.S __divsi3.S __moddi3.S __modsi3.S \
__udivdi3.S __udivsi3.S __umoddi3.S __umodsi3.S _setjmp.S fabs.S \
- flt_rounds.c fpgetmask.c fpgetround.c fpsetmask.c \
+ _set_tp.c flt_rounds.c fpgetmask.c fpgetround.c fpsetmask.c \
fpsetround.c infinity.c \
ldexp.c makecontext.c modf.c setjmp.S signalcontext.c sigsetjmp.S
diff --git a/lib/libc/ia64/gen/_set_tp.c b/lib/libc/ia64/gen/_set_tp.c
new file mode 100644
index 0000000..2419e10
--- /dev/null
+++ b/lib/libc/ia64/gen/_set_tp.c
@@ -0,0 +1,35 @@
+/*-
+ * Copyright (c) 2004 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+void
+_set_tp(void *tpval)
+{
+ register void* tp __asm__("r13");
+
+ tp = tpval;
+}
diff --git a/lib/libc/include/libc_private.h b/lib/libc/include/libc_private.h
index f18dde5..0f170db 100644
--- a/lib/libc/include/libc_private.h
+++ b/lib/libc/include/libc_private.h
@@ -113,6 +113,15 @@ extern pthread_func_entry_t __thr_jtable[];
int _yp_check(char **);
#endif
+/*
+ * Initialise TLS for static programs
+ */
+void _init_tls(void);
+
+/*
+ * Set the TLS thread pointer
+ */
+void _set_tp(void *tp);
/*
* This is a pointer in the C run-time startup code. It is used
diff --git a/lib/libc/powerpc/gen/Makefile.inc b/lib/libc/powerpc/gen/Makefile.inc
index 7e23dfb..4f8f0ea 100644
--- a/lib/libc/powerpc/gen/Makefile.inc
+++ b/lib/libc/powerpc/gen/Makefile.inc
@@ -3,6 +3,7 @@
SRCS += _ctx_start.S fabs.S flt_rounds.c fpgetmask.c fpgetround.c \
fpgetsticky.c fpsetmask.c fpsetround.c fpsetsticky.c \
infinity.c ldexp.c makecontext.c modf.c _setjmp.S \
- setjmp.S sigsetjmp.S signalcontext.c syncicache.c
+ setjmp.S sigsetjmp.S signalcontext.c syncicache.c \
+ _set_tp.c
diff --git a/lib/libc/powerpc/gen/_set_tp.c b/lib/libc/powerpc/gen/_set_tp.c
new file mode 100644
index 0000000..045416d
--- /dev/null
+++ b/lib/libc/powerpc/gen/_set_tp.c
@@ -0,0 +1,35 @@
+/*-
+ * Copyright (c) 2004 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+void
+_set_tp(void *tpval)
+{
+ register void* tp __asm__("r2");
+
+ tp = (char*) tpval + 0x7008;
+}
diff --git a/lib/libc/sparc64/gen/Makefile.inc b/lib/libc/sparc64/gen/Makefile.inc
index 022a4a3e..c228fc0 100644
--- a/lib/libc/sparc64/gen/Makefile.inc
+++ b/lib/libc/sparc64/gen/Makefile.inc
@@ -3,4 +3,4 @@
SRCS+= _ctx_start.S _setjmp.S fabs.S fixunsdfsi.S flt_rounds.c fpgetmask.c \
fpgetround.c fpgetsticky.c fpsetmask.c fpsetround.c fpsetsticky.c \
infinity.c ldexp.c makecontext.c modf.S \
- signalcontext.c setjmp.S sigsetjmp.S
+ signalcontext.c setjmp.S sigsetjmp.S _set_tp.c
diff --git a/lib/libc/sparc64/gen/_set_tp.c b/lib/libc/sparc64/gen/_set_tp.c
new file mode 100644
index 0000000..6255fd3
--- /dev/null
+++ b/lib/libc/sparc64/gen/_set_tp.c
@@ -0,0 +1,35 @@
+/*-
+ * Copyright (c) 2004 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+void
+_set_tp(void *tpval)
+{
+ register void* tp __asm__("%g7");
+
+ tp = tpval;
+}
OpenPOWER on IntegriCloud