diff options
author | Roland McGrath <roland@gnu.org> | 2002-12-04 12:30:40 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 2002-12-04 12:30:40 +0000 |
commit | 216455bc284f57dbaf939059f815935e23456c02 (patch) | |
tree | 3ae488a18ace0ebe18d7923eae29ae65a3badada /sysdeps/generic | |
parent | 68dc80ca28a192d686b3190373df8468b4ce5cb8 (diff) | |
download | glibc-216455bc284f57dbaf939059f815935e23456c02.tar.gz glibc-216455bc284f57dbaf939059f815935e23456c02.tar.xz 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 'sysdeps/generic')
-rw-r--r-- | sysdeps/generic/dl-tls.c | 36 | ||||
-rw-r--r-- | sysdeps/generic/libc-tls.c | 85 |
2 files changed, 93 insertions, 28 deletions
diff --git a/sysdeps/generic/dl-tls.c b/sysdeps/generic/dl-tls.c index 850df8d76f..550de56530 100644 --- a/sysdeps/generic/dl-tls.c +++ b/sysdeps/generic/dl-tls.c @@ -110,6 +110,7 @@ _dl_next_tls_modid (void) return result; } +# ifdef SHARED void internal_function @@ -204,6 +205,41 @@ _dl_determine_tlsoffset (void) } +/* This is called only when the data structure setup was skipped at startup, + when there was no need for it then. Now we have dynamically loaded + something needing TLS, or libpthread needs it. */ +int +internal_function +_dl_tls_setup (void) +{ + assert (GL(dl_tls_dtv_slotinfo_list) == NULL); + assert (GL(dl_tls_max_dtv_idx) == 0); + + const size_t nelem = 2 + TLS_SLOTINFO_SURPLUS; + + GL(dl_tls_dtv_slotinfo_list) = + malloc (sizeof (struct dtv_slotinfo_list) + + nelem * sizeof (struct dtv_slotinfo)); + if (GL(dl_tls_dtv_slotinfo_list) == NULL) + return -1; + + memset (GL(dl_tls_dtv_slotinfo_list)->slotinfo, '\0', + nelem * sizeof (struct dtv_slotinfo)); + GL(dl_tls_dtv_slotinfo_list)->len = nelem; + GL(dl_tls_dtv_slotinfo_list)->next = NULL; + + /* Number of elements in the static TLS block. It can't be zero + because of various assumptions. The one element is null. */ + GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx) = 1; + + /* This initializes more variables for us. */ + _dl_determine_tlsoffset (); + + return 0; +} +rtld_hidden_def (_dl_tls_setup) +# endif + static void * internal_function allocate_dtv (void *result) diff --git a/sysdeps/generic/libc-tls.c b/sysdeps/generic/libc-tls.c index a6a0504f44..756a2bf57c 100644 --- a/sysdeps/generic/libc-tls.c +++ b/sysdeps/generic/libc-tls.c @@ -74,6 +74,35 @@ size_t _dl_tls_generation; TLS_INIT_HELPER #endif +static inline void +init_slotinfo (void) +{ + /* Create the slotinfo list. */ + static_slotinfo.si.len = (((char *) (&static_slotinfo + 1) + - (char *) &static_slotinfo.si.slotinfo[0]) + / sizeof static_slotinfo.si.slotinfo[0]); + // static_slotinfo.si.next = NULL; already zero + + /* The slotinfo list. Will be extended by the code doing dynamic + linking. */ + GL(dl_tls_max_dtv_idx) = 1; + GL(dl_tls_dtv_slotinfo_list) = &static_slotinfo.si; +} + +static inline void +init_static_tls (size_t memsz, size_t align) +{ + /* That is the size of the TLS memory for this object. The initialized + value of _dl_tls_static_size is provided by dl-open.c to request some + surplus that permits dynamic loading of modules with IE-model TLS. */ + GL(dl_tls_static_size) = roundup (memsz + GL(dl_tls_static_size), + TLS_TCB_ALIGN); + GL(dl_tls_static_used) = memsz; + /* The alignment requirement for the static TLS block. */ + GL(dl_tls_static_align) = align; + /* Number of elements in the static TLS block. */ + GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx); +} void __libc_setup_tls (size_t tcbsize, size_t tcbalign) @@ -117,8 +146,8 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign) to request some surplus that permits dynamic loading of modules with IE-model TLS. */ # if TLS_TCB_AT_TP - tlsblock = __sbrk (roundup (memsz, tcbalign) + tcbsize + max_align - + GL(dl_tls_static_size)); + tcb_offset = roundup (memsz + GL(dl_tls_static_size), tcbalign); + tlsblock = __sbrk (tcb_offset + tcbsize + max_align); # elif TLS_DTV_AT_TP tlsblock = __sbrk (roundup (tcbsize, align) + memsz + max_align + GL(dl_tls_static_size)); @@ -138,10 +167,13 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign) /* Initialize the TLS block. */ # if TLS_TCB_AT_TP - static_dtv[2].pointer = tlsblock; + static_dtv[2].pointer = ((char *) tlsblock + tcb_offset + - roundup (memsz, align)); + static_map.l_tls_offset = roundup (memsz, align); # elif TLS_DTV_AT_TP tcb_offset = roundup (tcbsize, align); static_dtv[2].pointer = (char *) tlsblock + tcb_offset; + static_map.l_tls_offset = tcb_offset; # else # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" # endif @@ -152,8 +184,6 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign) /* Initialize the thread pointer. */ # if TLS_TCB_AT_TP - tcb_offset = roundup (memsz, tcbalign); - INSTALL_DTV ((char *) tlsblock + tcb_offset, static_dtv); TLS_INIT_TP ((char *) tlsblock + tcb_offset, 0); @@ -171,39 +201,38 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign) static_map.l_tls_blocksize = memsz; static_map.l_tls_initimage = initimage; static_map.l_tls_initimage_size = filesz; - static_map.l_tls_offset = tcb_offset; static_map.l_type = lt_executable; static_map.l_tls_modid = 1; - /* Create the slotinfo list. */ - static_slotinfo.si.len = (((char *) (&static_slotinfo + 1) - - (char *) &static_slotinfo.si.slotinfo[0]) - / sizeof static_slotinfo.si.slotinfo[0]); - // static_slotinfo.si.next = NULL; already zero - - static_slotinfo.si.slotinfo[1].gen = 0; + init_slotinfo (); + // static_slotinfo.si.slotinfo[1].gen = 0; already zero static_slotinfo.si.slotinfo[1].map = &static_map; - /* The slotinfo list. Will be extended by the code doing dynamic - linking. */ - GL(dl_tls_max_dtv_idx) = 1; - GL(dl_tls_dtv_slotinfo_list) = &static_slotinfo.si; - memsz = roundup (memsz, align ?: 1); + # if TLS_TCB_AT_TP memsz += tcbsize; # endif - /* That is the size of the TLS memory for this object. The initialized - value of _dl_tls_static_size is provided by dl-open.c to request some - surplus that permits dynamic loading of modules with IE-model TLS. */ - GL(dl_tls_static_size) = roundup (memsz + GL(dl_tls_static_size), - TLS_TCB_ALIGN); - GL(dl_tls_static_used) = memsz; - /* The alignment requirement for the static TLS block. */ - GL(dl_tls_static_align) = MAX (TLS_TCB_ALIGN, max_align); - /* Number of elements in the static TLS block. */ - GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx); + init_static_tls (memsz, MAX (TLS_TCB_ALIGN, max_align)); +} + +/* This is called only when the data structure setup was skipped at startup, + when there was no need for it then. Now we have dynamically loaded + something needing TLS, or libpthread needs it. */ +int +internal_function +_dl_tls_setup (void) +{ + init_slotinfo (); + init_static_tls ( +# if TLS_TCB_AT_TP + TLS_TCB_SIZE, +# else + 0, +# endif + TLS_TCB_ALIGN); + return 0; } |