Index: gnu/usr.bin/cc/cc_tools/auto-host.h =================================================================== --- gnu/usr.bin/cc/cc_tools/auto-host.h (revision 231101) +++ gnu/usr.bin/cc/cc_tools/auto-host.h (working copy) @@ -287,10 +287,8 @@ /* Define if your assembler supports thread-local storage. */ #ifndef USED_FOR_TARGET -#if !defined(__arm__) #define HAVE_AS_TLS 1 #endif -#endif /* Define to 1 if you have the `atoll' function. */ Index: lib/libthr/arch/arm/arm/pthread_md.c =================================================================== --- lib/libthr/arch/arm/arm/pthread_md.c (revision 231101) +++ lib/libthr/arch/arm/arm/pthread_md.c (working copy) @@ -37,14 +37,17 @@ { struct tcb *tcb; - tcb = malloc(sizeof(struct tcb)); + tcb = _rtld_allocate_tls((initial) ? _tcb_get() : NULL, + sizeof(struct tcb), 16); if (tcb) tcb->tcb_thread = thread; + return (tcb); } void _tcb_dtor(struct tcb *tcb) { - free(tcb); + + _rtld_free_tls(tcb, sizeof(struct tcb), 16); } Index: lib/libthr/arch/arm/include/pthread_md.h =================================================================== --- lib/libthr/arch/arm/include/pthread_md.h (revision 231101) +++ lib/libthr/arch/arm/include/pthread_md.h (working copy) @@ -43,10 +43,8 @@ * Variant II tcb, first two members are required by rtld. */ struct tcb { - struct tcb *tcb_self; /* required by rtld */ void *tcb_dtv; /* required by rtld */ struct pthread *tcb_thread; /* our hook */ - void *tcb_spare[1]; }; /* Index: lib/libc/arm/gen/Makefile.inc =================================================================== --- lib/libc/arm/gen/Makefile.inc (revision 231101) +++ lib/libc/arm/gen/Makefile.inc (working copy) @@ -3,4 +3,4 @@ SRCS+= _ctx_start.S _setjmp.S _set_tp.c alloca.S fabs.c \ getcontextx.c infinity.c ldexp.c makecontext.c \ - setjmp.S signalcontext.c sigsetjmp.S divsi3.S flt_rounds.c + __aeabi_read_tp.c setjmp.S signalcontext.c sigsetjmp.S divsi3.S flt_rounds.c Index: lib/libc/arm/gen/__aeabi_read_tp.c =================================================================== --- lib/libc/arm/gen/__aeabi_read_tp.c (revision 0) +++ lib/libc/arm/gen/__aeabi_read_tp.c (working copy) @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2012 Oleksandr Tymoshenko + * 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 +__FBSDID("$FreeBSD$"); + +#include + +#include "machine/sysarch.h" + +void * +__aeabi_read_tp() +{ + void **_tp = (void **)ARM_TP_ADDRESS; + + return (*_tp); +} Index: libexec/rtld-elf/arm/reloc.c =================================================================== --- libexec/rtld-elf/arm/reloc.c (revision 231101) +++ libexec/rtld-elf/arm/reloc.c (working copy) @@ -10,6 +10,9 @@ #include #include #include + +#include "machine/sysarch.h" + #include "debug.h" #include "rtld.h" @@ -233,6 +236,63 @@ dbg("COPY (avoid in main)"); break; + case R_ARM_TLS_DTPOFF32: + def = find_symdef(symnum, obj, &defobj, false, cache, + lockstate); + if (def == NULL) + return -1; + + tmp = (Elf_Addr)(def->st_value); + if (__predict_true(RELOC_ALIGNED_P(where))) + *where = tmp; + else + store_ptr(where, tmp); + + dbg("TLS_DTPOFF32 %s in %s --> %p", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)tmp); + + break; + case R_ARM_TLS_DTPMOD32: + def = find_symdef(symnum, obj, &defobj, false, cache, + lockstate); + if (def == NULL) + return -1; + + tmp = (Elf_Addr)(defobj->tlsindex); + if (__predict_true(RELOC_ALIGNED_P(where))) + *where = tmp; + else + store_ptr(where, tmp); + + dbg("TLS_DTPMOD32 %s in %s --> %p", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)tmp); + + break; + + case R_ARM_TLS_TPOFF32: + def = find_symdef(symnum, obj, &defobj, false, cache, + lockstate); + if (def == NULL) + return -1; + + if (!defobj->tls_done && allocate_tls_offset(obj)) + return -1; + + /* XXX: FIXME */ + tmp = (Elf_Addr)def->st_value + defobj->tlsoffset + + TLS_TCB_SIZE; + if (__predict_true(RELOC_ALIGNED_P(where))) + *where = tmp; + else + store_ptr(where, tmp); + dbg("TLS_TPOFF32 %s in %s --> %p", + obj->strtab + obj->symtab[symnum].st_name, + obj->path, (void *)tmp); + break; + + default: dbg("sym = %lu, type = %lu, offset = %p, " "contents = %p, symbol = %s", @@ -369,11 +429,26 @@ void allocate_initial_tls(Obj_Entry *objs) { - + void **_tp = (void **)ARM_TP_ADDRESS; + + /* + * Fix the size of the static TLS block by using the maximum + * offset allocated so far and adding a bit for dynamic modules to + * use. + */ + + tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA; + + (*_tp) = (void *) allocate_tls(objs, NULL, TLS_TCB_SIZE, 8); } void * __tls_get_addr(tls_index* ti) { - return (NULL); + void **_tp = (void **)ARM_TP_ADDRESS; + char *p; + + p = tls_get_addr_common((Elf_Addr **)(*_tp), ti->ti_module, ti->ti_offset); + + return (p); } Index: libexec/rtld-elf/arm/rtld_machdep.h =================================================================== --- libexec/rtld-elf/arm/rtld_machdep.h (revision 231101) +++ libexec/rtld-elf/arm/rtld_machdep.h (working copy) @@ -48,20 +48,20 @@ #define call_initfini_pointer(obj, target) \ (((InitFunc)(target))()) +#define TLS_TCB_SIZE 8 typedef struct { unsigned long ti_module; unsigned long ti_offset; } tls_index; #define round(size, align) \ - (((size) + (align) - 1) & ~((align) - 1)) + (((size) + (align) - 1) & ~((align) - 1)) #define calculate_first_tls_offset(size, align) \ - round(size, align) + round(8, align) #define calculate_tls_offset(prev_offset, prev_size, size, align) \ - round(prev_offset + prev_size, align) + round(prev_offset + prev_size, align) #define calculate_tls_end(off, size) ((off) + (size)) - /* * Lazy binding entry point, called via PLT. */ Index: libexec/rtld-elf/rtld.c =================================================================== --- libexec/rtld-elf/rtld.c (revision 231347) +++ libexec/rtld-elf/rtld.c (working copy) @@ -3541,10 +3541,8 @@ return (void*) (dtv[index + 1] + offset); } -/* XXX not sure what variants to use for arm. */ +#if defined(__arm__) || defined(__ia64__) || defined(__mips__) || defined(__powerpc__) -#if defined(__ia64__) || defined(__powerpc__) || defined(__mips__) - /* * Allocate Static TLS using the Variant I method. */ @@ -3624,8 +3622,7 @@ #endif -#if defined(__i386__) || defined(__amd64__) || defined(__sparc64__) || \ - defined(__arm__) +#if defined(__i386__) || defined(__amd64__) || defined(__sparc64__) /* * Allocate Static TLS using the Variant II method. Index: sys/sys/elf_common.h =================================================================== --- sys/sys/elf_common.h (revision 231101) +++ sys/sys/elf_common.h (working copy) @@ -633,6 +633,10 @@ #define R_ARM_THM_SWI8 14 #define R_ARM_XPC25 15 #define R_ARM_THM_XPC22 16 +/* TLS relocations */ +#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ +#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */ +#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */ #define R_ARM_COPY 20 /* Copy data from shared object. */ #define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */ #define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */ Index: sys/arm/arm/sys_machdep.c =================================================================== --- sys/arm/arm/sys_machdep.c (revision 231101) +++ sys/arm/arm/sys_machdep.c (working copy) @@ -89,14 +89,26 @@ { td->td_md.md_tp = (register_t)args; + if (td == curthread) { + critical_enter(); +#if !defined(SMP) + *(register_t *)ARM_TP_ADDRESS = (register_t)args; +#else + set_tls((void *)tls_base); +#endif + critical_exit(); + } + return (0); } static int arm32_get_tp(struct thread *td, void *args) { + void *tp; + tp = (void*)td->td_md.md_tp; + td->td_retval[0] = copyout(&tp, args, sizeof(tp)); - td->td_retval[0] = td->td_md.md_tp; return (0); }