3434
3535#include <sys/cdefs.h>
3636#include <sys/param.h>
37+ #include <assert.h>
3738#include <stdlib.h>
3839#include <string.h>
3940#include <elf.h>
@@ -85,6 +86,7 @@ void __libc_free_tls(void *tls, size_t tcbsize, size_t tcbalign);
8586
8687static size_t tls_static_space ;
8788static size_t tls_init_size ;
89+ static size_t tls_init_align ;
8890static void * tls_init ;
8991#endif
9092
@@ -113,6 +115,37 @@ __libc_tls_get_addr(void *ti __unused)
113115
114116#define TLS_TCB_SIZE (2 * sizeof(void *))
115117
118+ static void *
119+ malloc_aligned (size_t size , size_t align )
120+ {
121+ uintptr_t memshift ;
122+ void * mem , * res ;
123+
124+ if (align < sizeof (void * ))
125+ align = sizeof (void * );
126+
127+ mem = __je_bootstrap_malloc (size + sizeof (void * ) + align - 1 );
128+ memshift = roundup2 ((uintptr_t )mem + sizeof (void * ), align ) - (uintptr_t )mem ;
129+ res = (void * )((uintptr_t )mem + memshift );
130+ * (void * * )((uintptr_t )res - sizeof (void * )) = mem ;
131+ return (res );
132+ }
133+
134+ static void
135+ free_aligned (void * ptr )
136+ {
137+ void * mem ;
138+ uintptr_t x ;
139+
140+ if (ptr == NULL )
141+ return ;
142+
143+ x = (uintptr_t )ptr ;
144+ x -= sizeof (void * );
145+ mem = * (void * * )x ;
146+ __je_bootstrap_free (mem );
147+ }
148+
116149/*
117150 * Free Static TLS using the Variant I method.
118151 */
@@ -122,47 +155,50 @@ __libc_free_tls(void *tcb, size_t tcbsize, size_t tcbalign __unused)
122155 Elf_Addr * dtv ;
123156 Elf_Addr * * tls ;
124157
125- tls = (Elf_Addr * * )(( Elf_Addr ) tcb + tcbsize - TLS_TCB_SIZE ) ;
158+ tls = (Elf_Addr * * )tcb ;
126159 dtv = tls [0 ];
127160 __je_bootstrap_free (dtv );
128- __je_bootstrap_free ( tcb );
161+ free_aligned ( tls );
129162}
130163
131164/*
132165 * Allocate Static TLS using the Variant I method.
133166 */
134167void *
135- __libc_allocate_tls (void * oldtcb , size_t tcbsize , size_t tcbalign __unused )
168+ __libc_allocate_tls (void * oldtcb , size_t tcbsize , size_t tcbalign )
136169{
137170 Elf_Addr * dtv ;
138171 Elf_Addr * * tls ;
139- char * tcb ;
140172
141173 if (oldtcb != NULL && tcbsize == TLS_TCB_SIZE )
142174 return (oldtcb );
143175
144- tcb = __je_bootstrap_calloc (1 , tls_static_space + tcbsize - TLS_TCB_SIZE );
145- tls = (Elf_Addr * * )(tcb + tcbsize - TLS_TCB_SIZE );
176+ assert (tcbalign >= TLS_TCB_ALIGN );
177+ assert (tcbsize == TLS_TCB_SIZE );
178+
179+ tcbsize = roundup2 (tcbsize , tcbalign );
180+ tls = malloc_aligned (tcbsize + tls_static_space , tcbalign );
181+ memset (tls , 0 , tcbsize + tls_static_space );
146182
147183 if (oldtcb != NULL ) {
148- memcpy (tls , oldtcb , tls_static_space );
184+ memcpy (tls , oldtcb , tcbsize + tls_static_space );
149185 __je_bootstrap_free (oldtcb );
150186
151187 /* Adjust the DTV. */
152188 dtv = tls [0 ];
153- dtv [2 ] = (Elf_Addr )tls + TLS_TCB_SIZE ;
189+ dtv [2 ] = (Elf_Addr )tls + tcbsize ;
154190 } else {
155191 dtv = __je_bootstrap_malloc (3 * sizeof (Elf_Addr ));
156192 tls [0 ] = dtv ;
157- dtv [0 ] = 1 ;
158- dtv [1 ] = 1 ;
159- dtv [2 ] = (Elf_Addr )tls + TLS_TCB_SIZE ;
193+ dtv [0 ] = 1 ; /* Generation. */
194+ dtv [1 ] = 1 ; /* Segments count. */
195+ dtv [2 ] = (Elf_Addr )tls + tcbsize ;
160196
161197 if (tls_init_size > 0 )
162198 memcpy ((void * )dtv [2 ], tls_init , tls_init_size );
163199 }
164200
165- return (tcb );
201+ return (tls );
166202}
167203
168204#endif
@@ -305,18 +341,14 @@ _init_tls(void)
305341 tls_static_space = roundup2 (phdr [i ].p_memsz ,
306342 phdr [i ].p_align );
307343 tls_init_size = phdr [i ].p_filesz ;
344+ tls_init_align = phdr [i ].p_align ;
308345 tls_init = (void * ) phdr [i ].p_vaddr ;
346+ break ;
309347 }
310348 }
311349
312- #ifdef TLS_VARIANT_I
313- /*
314- * tls_static_space should include space for TLS structure
315- */
316- tls_static_space += TLS_TCB_SIZE ;
317- #endif
318-
319- tls = _rtld_allocate_tls (NULL , TLS_TCB_SIZE , TLS_TCB_ALIGN );
350+ tls = _rtld_allocate_tls (NULL , TLS_TCB_SIZE ,
351+ MAX (TLS_TCB_ALIGN , tls_init_align ));
320352
321353 _set_tp (tls );
322354#endif
0 commit comments