aboutsummaryrefslogtreecommitdiff
path: root/elf/dl-load.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2002-12-04 12:30:40 +0000
committerRoland McGrath <roland@gnu.org>2002-12-04 12:30:40 +0000
commit216455bc284f57dbaf939059f815935e23456c02 (patch)
tree3ae488a18ace0ebe18d7923eae29ae65a3badada /elf/dl-load.c
parent68dc80ca28a192d686b3190373df8468b4ce5cb8 (diff)
downloadglibc-216455bc284f57dbaf939059f815935e23456c02.tar
glibc-216455bc284f57dbaf939059f815935e23456c02.tar.gz
glibc-216455bc284f57dbaf939059f815935e23456c02.tar.bz2
glibc-216455bc284f57dbaf939059f815935e23456c02.zip
* 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 <davmac@ozonline.com.au>. * 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.
Diffstat (limited to 'elf/dl-load.c')
-rw-r--r--elf/dl-load.c56
1 files changed, 44 insertions, 12 deletions
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