tls.c (160711) | tls.c (161800) |
---|---|
1/*- 2 * Copyright (c) 2004 Doug Rabson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * | 1/*- 2 * Copyright (c) 2004 Doug Rabson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 9 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * |
26 * $FreeBSD: head/lib/libc/gen/tls.c 160711 2006-07-26 16:56:56Z imp $ | 26 * $FreeBSD: head/lib/libc/gen/tls.c 161800 2006-09-01 06:13:16Z marcel $ |
27 */ 28 29/* 30 * Define stubs for TLS internals so that programs and libraries can 31 * link. These functions will be replaced by functional versions at 32 * runtime from ld-elf.so.1. 33 */ 34 --- 18 unchanged lines hidden (view full) --- 53void * __libc_tls_get_addr(void *); 54__weak_reference(__libc_tls_get_addr, __tls_get_addr); 55 56void *_rtld_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign); 57void _rtld_free_tls(void *tls, size_t tcbsize, size_t tcbalign); 58void *__libc_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign); 59void __libc_free_tls(void *tls, size_t tcbsize, size_t tcbalign); 60 | 27 */ 28 29/* 30 * Define stubs for TLS internals so that programs and libraries can 31 * link. These functions will be replaced by functional versions at 32 * runtime from ld-elf.so.1. 33 */ 34 --- 18 unchanged lines hidden (view full) --- 53void * __libc_tls_get_addr(void *); 54__weak_reference(__libc_tls_get_addr, __tls_get_addr); 55 56void *_rtld_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign); 57void _rtld_free_tls(void *tls, size_t tcbsize, size_t tcbalign); 58void *__libc_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign); 59void __libc_free_tls(void *tls, size_t tcbsize, size_t tcbalign); 60 |
61#if defined(__ia64__) || defined(__alpha__) || defined(__powerpc__) | 61#if defined(__ia64__) || defined(__powerpc__) |
62#define TLS_VARIANT_I 63#endif 64#if defined(__i386__) || defined(__amd64__) || defined(__sparc64__) || \ 65 defined(__arm__) 66#define TLS_VARIANT_II 67#endif 68 69#ifndef PIC 70 71#define round(size, align) \ 72 (((size) + (align) - 1) & ~((align) - 1)) 73 74static size_t tls_static_space; 75static size_t tls_init_size; | 62#define TLS_VARIANT_I 63#endif 64#if defined(__i386__) || defined(__amd64__) || defined(__sparc64__) || \ 65 defined(__arm__) 66#define TLS_VARIANT_II 67#endif 68 69#ifndef PIC 70 71#define round(size, align) \ 72 (((size) + (align) - 1) & ~((align) - 1)) 73 74static size_t tls_static_space; 75static size_t tls_init_size; |
76#ifdef TLS_VARIANT_I 77static size_t tls_init_offset; 78#endif | |
79static void *tls_init; 80#endif 81 82#ifdef __i386__ 83 84/* GNU ABI */ 85 86__attribute__((__regparm__(1))) --- 10 unchanged lines hidden (view full) --- 97{ 98 return (0); 99} 100 101#ifndef PIC 102 103#ifdef TLS_VARIANT_I 104 | 76static void *tls_init; 77#endif 78 79#ifdef __i386__ 80 81/* GNU ABI */ 82 83__attribute__((__regparm__(1))) --- 10 unchanged lines hidden (view full) --- 94{ 95 return (0); 96} 97 98#ifndef PIC 99 100#ifdef TLS_VARIANT_I 101 |
102#define TLS_TCB_SIZE (2 * sizeof(void *)) 103 |
|
105/* 106 * Free Static TLS using the Variant I method. 107 */ 108void | 104/* 105 * Free Static TLS using the Variant I method. 106 */ 107void |
109__libc_free_tls(void *tls, size_t tcbsize __unused, size_t tcbalign __unused) | 108__libc_free_tls(void *tcb, size_t tcbsize, size_t tcbalign __unused) |
110{ | 109{ |
111 Elf_Addr* dtv; | 110 Elf_Addr *dtv; 111 Elf_Addr **tls; |
112 | 112 |
113 dtv = ((Elf_Addr**)tls)[0]; 114 free(tls); | 113 tls = (Elf_Addr **)((Elf_Addr)tcb + tcbsize - TLS_TCB_SIZE); 114 dtv = tls[0]; |
115 free(dtv); | 115 free(dtv); |
116 free(tcb); |
|
116} 117 118/* 119 * Allocate Static TLS using the Variant I method. 120 */ 121void * | 117} 118 119/* 120 * Allocate Static TLS using the Variant I method. 121 */ 122void * |
122__libc_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign __unused) | 123__libc_allocate_tls(void *oldtcb, size_t tcbsize, size_t tcbalign __unused) |
123{ | 124{ |
124 size_t size; 125 char *tls; | |
126 Elf_Addr *dtv; | 125 Elf_Addr *dtv; |
126 Elf_Addr **tls; 127 char *tcb; |
|
127 | 128 |
128 size = tls_static_space; 129 if (size < tcbsize) 130 size = tcbsize; | 129 if (oldtcb != NULL && tcbsize == TLS_TCB_SIZE) 130 return (oldtcb); |
131 | 131 |
132 tls = calloc(1, size); 133 dtv = malloc(3 * sizeof(Elf_Addr)); | 132 tcb = calloc(1, tls_static_space + tcbsize); 133 tls = (Elf_Addr **)(tcb + tcbsize - TLS_TCB_SIZE); |
134 | 134 |
135 *(Elf_Addr **) tls = dtv; | 135 if (oldtcb != NULL) { 136 memcpy(tls, oldtcb, tls_static_space + TLS_TCB_SIZE); 137 free(oldtcb); |
136 | 138 |
137 dtv[0] = 1; 138 dtv[1] = 1; 139 dtv[2] = (Elf_Addr)(tls + tls_init_offset); 140 if (oldtls) { 141 /* 142 * Copy the static TLS block over whole. 143 */ 144 memcpy(tls + tls_init_offset, 145 (char *)oldtls + tls_init_offset, 146 tls_static_space - tls_init_offset); 147 148 /* 149 * We assume that this block was the one we created with 150 * allocate_initial_tls(). 151 */ 152 _rtld_free_tls(oldtls, 2 * sizeof(Elf_Addr), sizeof(Elf_Addr)); | 139 /* Adjust the DTV. */ 140 dtv = tls[0]; 141 dtv[2] = (Elf_Addr)tls + TLS_TCB_SIZE; |
153 } else { | 142 } else { |
154 memcpy(tls + tls_init_offset, tls_init, tls_init_size); 155 memset(tls + tls_init_offset + tls_init_size, 156 0, tls_static_space - tls_init_size); | 143 dtv = malloc(3 * sizeof(Elf_Addr)); 144 tls[0] = dtv; 145 dtv[0] = 1; 146 dtv[1] = 1; 147 dtv[2] = (Elf_Addr)tls + TLS_TCB_SIZE; 148 149 if (tls_init_size > 0) 150 memcpy((void*)dtv[2], tls_init, tls_init_size); 151 if (tls_static_space > tls_init_size) 152 memset((void*)(dtv[2] + tls_init_size), 0, 153 tls_static_space - tls_init_size); |
157 } 158 | 154 } 155 |
159 return tls; | 156 return(tcb); |
160} 161 162#endif 163 164#ifdef TLS_VARIANT_II 165 | 157} 158 159#endif 160 161#ifdef TLS_VARIANT_II 162 |
163#define TLS_TCB_SIZE (3 * sizeof(Elf_Addr)) 164 |
|
166/* 167 * Free Static TLS using the Variant II method. 168 */ 169void 170__libc_free_tls(void *tcb, size_t tcbsize __unused, size_t tcbalign) 171{ 172 size_t size; 173 Elf_Addr* dtv; --- 114 unchanged lines hidden (view full) --- 288 break; 289 } 290 } 291 if (phdr == 0 || phent != sizeof(Elf_Phdr) || phnum == 0) 292 return; 293 294 for (i = 0; (unsigned) i < phnum; i++) { 295 if (phdr[i].p_type == PT_TLS) { | 165/* 166 * Free Static TLS using the Variant II method. 167 */ 168void 169__libc_free_tls(void *tcb, size_t tcbsize __unused, size_t tcbalign) 170{ 171 size_t size; 172 Elf_Addr* dtv; --- 114 unchanged lines hidden (view full) --- 287 break; 288 } 289 } 290 if (phdr == 0 || phent != sizeof(Elf_Phdr) || phnum == 0) 291 return; 292 293 for (i = 0; (unsigned) i < phnum; i++) { 294 if (phdr[i].p_type == PT_TLS) { |
296#ifdef TLS_VARIANT_I 297 tls_static_space = round(2*sizeof(Elf_Addr), 298 phdr[i].p_align) + phdr[i].p_memsz; 299 tls_init_offset = round(2*sizeof(Elf_Addr), 300 phdr[i].p_align); 301#else | |
302 tls_static_space = round(phdr[i].p_memsz, 303 phdr[i].p_align); | 295 tls_static_space = round(phdr[i].p_memsz, 296 phdr[i].p_align); |
304#endif | |
305 tls_init_size = phdr[i].p_filesz; 306 tls_init = (void*) phdr[i].p_vaddr; 307 } 308 } 309 | 297 tls_init_size = phdr[i].p_filesz; 298 tls_init = (void*) phdr[i].p_vaddr; 299 } 300 } 301 |
310 tls = _rtld_allocate_tls(NULL, 3*sizeof(Elf_Addr), 311 sizeof(Elf_Addr)); | 302 tls = _rtld_allocate_tls(NULL, TLS_TCB_SIZE, 1); |
312 313 _set_tp(tls); 314#endif 315} | 303 304 _set_tp(tls); 305#endif 306} |