@@ -37,6 +37,18 @@ struct pthread_tcb {
3737extern char TLS_START __attribute__((weak ));
3838extern char TLS_END __attribute__((weak ));
3939
40+ /*
41+ * ELF TLS initialization image, provided by the linker script:
42+ * - .tdata is the initialized portion; its file image lives at
43+ * __tdata_source and is __tdata_size bytes long.
44+ * - .tbss is the zero-initialized portion, __tbss_size bytes long,
45+ * laid out immediately after .tdata. It is NOBITS: it has no valid
46+ * source bytes in the file and MUST be zero-filled, never copied.
47+ */
48+ extern char __tdata_source __attribute__((weak ));
49+ extern char __tdata_size __attribute__((weak ));
50+ extern char __tbss_size __attribute__((weak ));
51+
4052static char * elftls_start ;
4153static unsigned int elftls_size ;
4254
@@ -185,15 +197,24 @@ int pthread_join(pthread_t thread, void **retval)
185197static struct pthread_tcb * pthread_create_common (struct pthread_tcb * dst )
186198{
187199 char * elftls_area ;
200+ size_t tdata_size = (size_t )& __tdata_size ;
201+ size_t tbss_size = (size_t )& __tbss_size ;
188202 /* init semaphores */
189203 pthread_sem_init_np (& dst -> joined ,0 ,0 );
190204 pthread_sem_init_np (& dst -> waiters ,0 ,0 );
191205 pthread_sem_init_np (& dst -> exiting ,0 ,0 );
192206 pthread_sem_init_np (& dst -> ack ,0 ,0 );
193- /* Copy ELF TLS area */
207+ /* Initialize the ELF TLS area per the TLS spec: copy the initialized
208+ * .tdata image, then zero-fill the .tbss portion. .tbss is NOBITS and
209+ * has no valid source bytes, so it must be memset, not memcpy'd --
210+ * otherwise thread-locals such as __cxa_eh_globals inherit garbage.
211+ */
194212 elftls_area = (char * )dst ;
195213 elftls_area -= elftls_size ;
196- memcpy (elftls_area ,elftls_start ,elftls_size );
214+ if (tdata_size != 0 )
215+ memcpy (elftls_area , & __tdata_source , tdata_size );
216+ if (tbss_size != 0 )
217+ memset (elftls_area + tdata_size , 0 , tbss_size );
197218 return dst ;
198219}
199220
0 commit comments