Skip to content

Commit 2f9a3b3

Browse files
authored
Merge pull request #78 from qualcomm/tls-fix
pthread: zero-fill .tbss when initializing thread TLS
2 parents e328788 + cb5c11c commit 2f9a3b3

1 file changed

Lines changed: 23 additions & 2 deletions

File tree

libs/posix/pthread/thread/pthread_thread.ref.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,18 @@ struct pthread_tcb {
3737
extern char TLS_START __attribute__((weak));
3838
extern 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+
4052
static char *elftls_start;
4153
static unsigned int elftls_size;
4254

@@ -185,15 +197,24 @@ int pthread_join(pthread_t thread, void **retval)
185197
static 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

Comments
 (0)