From 216455bc284f57dbaf939059f815935e23456c02 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Wed, 4 Dec 2002 12:30:40 +0000 Subject: * sysdeps/generic/ldsodefs.h (struct rtld_global): Move all [USE_TLS] members to the end, so a libpthread compiled with !USE_TLS will still find other members properly. * sysdeps/i386/i486/bits/string.h (__strcpy_g): Add dummy output operand for DEST memory. Fix dummy input operand to use SRC. Reported by Davin McCall . * sysdeps/generic/libc-tls.c (__libc_setup_tls): Account for TCB alignment when initializing the DTV entry. * elf/dl-load.c (_dl_map_object_from_fd): If we hit a TLS segment when TLS has not been set up, try to set it up if we can. * elf/tst-tls4.c: Revert last change. * elf/tst-tls5.c: Likewise. * elf/tst-tls6.c: Likewise. * elf/tst-tls7.c: Likewise. * elf/tst-tls8.c: Likewise. * elf/tst-tls9.c: Likewise. * sysdeps/generic/dl-tls.c [SHARED] (_dl_tls_setup): New function. * sysdeps/generic/ldsodefs.h: Declare it. * elf/Versions (ld: GLIBC_PRIVATE): Add it. * sysdeps/generic/libc-tls.c (init_slotinfo): New static inline function, broken out of __libc_setup_tls. (init_static_tls): Likewise. (__libc_setup_tls): Call them. (_dl_tls_setup): New function, uses new subroutines. * elf/dl-close.c (free_slotinfo): Make argument pointer to pointer. Clear the pointer when returning true. (libc_freeres_fn) [SHARED]: If GL(dl_initial_dtv) is null, free the first element of the slotinfo list too. * sysdeps/generic/dl-tls.c (_dl_determine_tlsoffset): Define only if [SHARED]. * sysdeps/generic/ldsodefs.h (_dl_next_tls_modid): Declare as hidden. (_dl_determine_tlsoffset): Likewise. * elf/rtld.c (_dl_initial_error_catch_tsd): Renamed from startup_error_tsd, made global. (dl_main): Update initialization. * elf/dl-tsd.c: Likewise. * sysdeps/generic/ldsodefs.h: Declare it. --- elf/dl-load.c | 56 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 12 deletions(-) (limited to 'elf/dl-load.c') diff --git a/elf/dl-load.c b/elf/dl-load.c index c550204ac5..d80f30813f 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -946,32 +946,64 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp, /* Nothing to do for an empty segment. */ break; + l->l_tls_blocksize = ph->p_memsz; + l->l_tls_align = ph->p_align; + l->l_tls_initimage_size = ph->p_filesz; + /* Since we don't know the load address yet only store the + offset. We will adjust it later. */ + l->l_tls_initimage = (void *) ph->p_vaddr; + /* If not loading the initial set of shared libraries, check whether we should permit loading a TLS segment. */ - if ( -# ifdef SHARED - __builtin_expect (l->l_type == lt_library, 1) || -# endif + if (__builtin_expect (l->l_type == lt_library, 1) /* If GL(dl_tls_max_dtv_idx) == 0, then rtld.c did not set up TLS data structures, so don't use them now. */ - __builtin_expect (GL(dl_tls_max_dtv_idx), 1) != 0) + || __builtin_expect (GL(dl_tls_max_dtv_idx), 1) != 0) { - l->l_tls_blocksize = ph->p_memsz; - l->l_tls_align = ph->p_align; - l->l_tls_initimage_size = ph->p_filesz; - /* Since we don't know the load address yet only store the - offset. We will adjust it later. */ - l->l_tls_initimage = (void *) ph->p_vaddr; - /* Assign the next available module ID. */ l->l_tls_modid = _dl_next_tls_modid (); break; } +# ifdef SHARED if (l->l_prev == NULL) /* We are loading the executable itself when the dynamic linker was executed directly. The setup will happen later. */ break; + + /* In a static binary there is no way to tell if we dynamically + loaded libpthread. */ + if (GL(dl_error_catch_tsd) == &_dl_initial_error_catch_tsd) +# endif + { + /* We have not yet loaded libpthread. + We can do the TLS setup right now! */ + + void *tcb; + + /* The first call allocates TLS bookkeeping data structures. + Then we allocate the TCB for the initial thread. */ + if (__builtin_expect (_dl_tls_setup (), 0) + || __builtin_expect ((tcb = _dl_allocate_tls (NULL)) == NULL, + 0)) + { + errval = ENOMEM; + errstring = N_("\ +cannot allocate TLS data structures for initial thread"); + goto call_lose; + } + + /* Now we install the TCB in the thread register. */ + if (__builtin_expect (TLS_INIT_TP (tcb, 0), 0) != -1) + { + /* Now we are all good. */ + l->l_tls_modid = ++GL(dl_tls_max_dtv_idx); + break; + } + + /* The kernel is too old or somesuch. */ + _dl_deallocate_tls (tcb, 1); + } #endif /* Uh-oh, the binary expects TLS support but we cannot -- cgit v1.2.3