From 2d14868942150183adaf0bc80b8ed6b70b65261e Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Tue, 3 Dec 2002 01:51:07 +0000 Subject: [PATCH] * elf/tst-tls4.c: Define an unused TLS variable here, so that no lazy TLS setup is required. * 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. * elf/rtld.c (dl_main): Remove [! SHARED] conditional from `if (GL(dl_tls_max_dtv_idx) > 0)' tests for doing TLS setup. * elf/dl-close.c (libc_freeres_fn): Check GL(dl_tls_dtv_slotinfo_list) for being null before calling free_slotinfo. * elf/dl-load.c (_dl_map_object_from_fd) [SHARED]: For PT_TLS in dynamic loading, bail with error if GL(dl_tls_max_dtv_idx) is zero. --- ChangeLog | 17 +++++++++++++++++ elf/dl-close.c | 17 ++++++++++------- elf/dl-load.c | 24 +++++++++++++++++++++--- elf/rtld.c | 16 ++++++++-------- elf/tst-tls4.c | 8 ++++++++ elf/tst-tls5.c | 9 +++++++++ elf/tst-tls6.c | 9 +++++++++ elf/tst-tls7.c | 9 +++++++++ elf/tst-tls8.c | 9 +++++++++ elf/tst-tls9.c | 9 +++++++++ linuxthreads/sysdeps/i386/tls.h | 28 +++++++++++++++++++++++++--- linuxthreads/tst-context.c | 11 +++++++++-- 12 files changed, 143 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index bbdfda3..593f6a6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2002-12-02 Roland McGrath + + * elf/tst-tls4.c: Define an unused TLS variable here, so that no lazy + TLS setup is required. + * 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. + + * elf/rtld.c (dl_main): Remove [! SHARED] conditional from + `if (GL(dl_tls_max_dtv_idx) > 0)' tests for doing TLS setup. + * elf/dl-close.c (libc_freeres_fn): Check GL(dl_tls_dtv_slotinfo_list) + for being null before calling free_slotinfo. + * elf/dl-load.c (_dl_map_object_from_fd) [SHARED]: For PT_TLS in + dynamic loading, bail with error if GL(dl_tls_max_dtv_idx) is zero. + 2002-11-30 Bruno Haible * iconv/gconv.h (__gconv_btowc_fct): New typedef. diff --git a/elf/dl-close.c b/elf/dl-close.c index 632f8ba..b5c2841 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -476,12 +476,15 @@ libc_freeres_fn (free_mem) } #ifdef USE_TLS - /* Free the memory allocated for the dtv slotinfo array. We can do - this only if all modules which used this memory are unloaded. - Also, the first element of the list does not have to be - deallocated. It was allocated in the dynamic linker (i.e., with - a different malloc). */ - if (free_slotinfo (GL(dl_tls_dtv_slotinfo_list)->next)) - GL(dl_tls_dtv_slotinfo_list)->next = NULL; + if (USE___THREAD || GL(dl_tls_dtv_slotinfo_list) != NULL) + { + /* Free the memory allocated for the dtv slotinfo array. We can do + this only if all modules which used this memory are unloaded. + Also, the first element of the list does not have to be + deallocated. It was allocated in the dynamic linker (i.e., with + a different malloc). */ + if (free_slotinfo (GL(dl_tls_dtv_slotinfo_list)->next)) + GL(dl_tls_dtv_slotinfo_list)->next = NULL; + } #endif } diff --git a/elf/dl-load.c b/elf/dl-load.c index 3452c0b..c550204 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -942,7 +942,19 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp, case PT_TLS: #ifdef USE_TLS - if (ph->p_memsz > 0) + if (ph->p_memsz == 0) + /* Nothing to do for an empty segment. */ + break; + + /* 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 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) { l->l_tls_blocksize = ph->p_memsz; l->l_tls_align = ph->p_align; @@ -953,14 +965,20 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp, /* Assign the next available module ID. */ l->l_tls_modid = _dl_next_tls_modid (); + break; } -#else + + if (l->l_prev == NULL) + /* We are loading the executable itself when the dynamic linker + was executed directly. The setup will happen later. */ + break; +#endif + /* Uh-oh, the binary expects TLS support but we cannot provide it. */ errval = 0; errstring = N_("cannot handle TLS data"); goto call_lose; -#endif break; } diff --git a/elf/rtld.c b/elf/rtld.c index 350cc70..6e20e15 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -1139,12 +1139,14 @@ of this helper program; chances are you did not intend to run this program.\n\ /* Assign a module ID. */ GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid (); -# ifndef SHARED - /* If dynamic loading of modules with TLS is impossible we do not - have to initialize any of the TLS functionality unless any of the - initial modules uses TLS. */ + /* We do not initialize any of the TLS functionality unless any of the + initial modules uses TLS. This makes dynamic loading of modules with + TLS impossible, but to support it requires either eagerly doing setup + now or lazily doing it later. Doing it now makes us incompatible with + an old kernel that can't perform TLS_INIT_TP, even if no TLS is ever + used. Trying to do it lazily is too hairy to try when there could be + multiple threads (from a non-TLS-using libpthread). */ if (GL(dl_tls_max_dtv_idx) > 0) -# endif { struct link_map *l; size_t nelem; @@ -1555,9 +1557,7 @@ cannot allocate TLS data structures for initial thread"); GL(dl_initial_searchlist) = *GL(dl_main_searchlist); #ifdef USE_TLS -# ifndef SHARED - if (GL(dl_tls_max_dtv_idx) > 0) -# endif + if (GL(dl_tls_max_dtv_idx) > 0 || USE___THREAD) { /* Now that we have completed relocation, the initializer data for the TLS blocks has its final values and we can copy them diff --git a/elf/tst-tls4.c b/elf/tst-tls4.c index f92ee53..32ec147 100644 --- a/elf/tst-tls4.c +++ b/elf/tst-tls4.c @@ -4,6 +4,14 @@ #include +#ifdef USE_TLS +# include "tls-macros.h" + +/* This gives the executable a TLS segment so that even if the libc.so + it loads has none (i.e. --with-tls --without-__thread), ld.so will + permit loading of objects with TLS segments. */ +COMMON_INT_DEF(loser); +#endif #define TEST_FUNCTION do_test () static int diff --git a/elf/tst-tls5.c b/elf/tst-tls5.c index a571d2c..c10015d 100644 --- a/elf/tst-tls5.c +++ b/elf/tst-tls5.c @@ -4,6 +4,15 @@ #include +#ifdef USE_TLS +# include "tls-macros.h" + +/* This gives the executable a TLS segment so that even if the libc.so + it loads has none (i.e. --with-tls --without-__thread), ld.so will + permit loading of objects with TLS segments. */ +COMMON_INT_DEF(loser); +#endif + #define TEST_FUNCTION do_test () static int diff --git a/elf/tst-tls6.c b/elf/tst-tls6.c index 2c015ef..3c5c7aa 100644 --- a/elf/tst-tls6.c +++ b/elf/tst-tls6.c @@ -5,6 +5,15 @@ #include #include +#ifdef USE_TLS +# include "tls-macros.h" + +/* This gives the executable a TLS segment so that even if the libc.so + it loads has none (i.e. --with-tls --without-__thread), ld.so will + permit loading of objects with TLS segments. */ +COMMON_INT_DEF(loser); +#endif + #define TEST_FUNCTION do_test () static int diff --git a/elf/tst-tls7.c b/elf/tst-tls7.c index 4f785fe..77d2016 100644 --- a/elf/tst-tls7.c +++ b/elf/tst-tls7.c @@ -5,6 +5,15 @@ #include #include +#ifdef USE_TLS +# include "tls-macros.h" + +/* This gives the executable a TLS segment so that even if the libc.so + it loads has none (i.e. --with-tls --without-__thread), ld.so will + permit loading of objects with TLS segments. */ +COMMON_INT_DEF(loser); +#endif + #define TEST_FUNCTION do_test () static int diff --git a/elf/tst-tls8.c b/elf/tst-tls8.c index e300bc5..7444c26 100644 --- a/elf/tst-tls8.c +++ b/elf/tst-tls8.c @@ -5,6 +5,15 @@ #include #include +#ifdef USE_TLS +# include "tls-macros.h" + +/* This gives the executable a TLS segment so that even if the libc.so + it loads has none (i.e. --with-tls --without-__thread), ld.so will + permit loading of objects with TLS segments. */ +COMMON_INT_DEF(loser); +#endif + #define TEST_FUNCTION do_test () static int diff --git a/elf/tst-tls9.c b/elf/tst-tls9.c index cd958e4..a679efc 100644 --- a/elf/tst-tls9.c +++ b/elf/tst-tls9.c @@ -5,6 +5,15 @@ #include #include +#ifdef USE_TLS +# include "tls-macros.h" + +/* This gives the executable a TLS segment so that even if the libc.so + it loads has none (i.e. --with-tls --without-__thread), ld.so will + permit loading of objects with TLS segments. */ +COMMON_INT_DEF(loser); +#endif + #define TEST_FUNCTION do_test () static int diff --git a/linuxthreads/sysdeps/i386/tls.h b/linuxthreads/sysdeps/i386/tls.h index 7715303..8bbe5f2 100644 --- a/linuxthreads/sysdeps/i386/tls.h +++ b/linuxthreads/sysdeps/i386/tls.h @@ -43,8 +43,17 @@ typedef struct #endif -/* We can support TLS only if the floating-stack support is available. */ -#if defined FLOATING_STACKS && defined HAVE_TLS_SUPPORT +/* We can support TLS only if the floating-stack support is available. + However, we want to compile in the support and test at runtime whether + the running kernel can support it or not. To avoid bothering with the + TLS support code at all, use configure --without-tls. + + We need USE_TLS to be consistently defined, for ldsodefs.h conditionals. + But some of the code below can cause problems in building libpthread + (e.g. useldt.h will defined FLOATING_STACKS when it shouldn't). */ + +#if defined HAVE_TLS_SUPPORT \ + && (defined FLOATING_STACKS || !defined IS_IN_libpthread) /* Signal that TLS support is available. */ # define USE_TLS 1 @@ -96,8 +105,21 @@ typedef struct # define TLS_LOAD_EBX # endif +# if __ASSUME_LDT_WORKS > 0 +# define TLS_DO_MODIFY_LDT_KERNEL_CHECK /* Nothing to do. */ +# else +# include "useldt.h" /* For the structure. */ +# define TLS_DO_MODIFY_LDT_KERNEL_CHECK \ + if (__builtin_expect (GL(dl_osversion) < 131939, 0)) \ + _dl_fatal_printf ("kernel %u.%u.%u cannot support thread-local storage\n",\ + (GL(dl_osversion) >> 16) & 0xff, \ + (GL(dl_osversion) >> 8) & 0xff, \ + (GL(dl_osversion) >> 0) & 0xff); +# endif + # define TLS_DO_MODIFY_LDT(descr, nr) \ ({ \ + TLS_DO_MODIFY_LDT_KERNEL_CHECK \ struct modify_ldt_ldt_s ldt_entry = \ { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ 1, 0, 0, 1, 0, 1, 0 }; \ @@ -177,7 +199,7 @@ typedef struct ({ struct _pthread_descr_struct *__descr; \ THREAD_GETMEM (__descr, p_header.data.dtvp); }) -# endif /* FLOATING_STACKS && HAVE_TLS_SUPPORT */ +# endif /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */ #endif /* __ASSEMBLER__ */ #endif /* tls.h */ diff --git a/linuxthreads/tst-context.c b/linuxthreads/tst-context.c index 5c3272a..2938a9f 100644 --- a/linuxthreads/tst-context.c +++ b/linuxthreads/tst-context.c @@ -1,3 +1,12 @@ +/* Ack, a hack! We need to get the proper definition, or lack thereof, + for FLOATING_STACKS. But when !IS_IN_libpthread, this can get defined + incidentally by . So kludge around it. */ + +#define IS_IN_libpthread +#include +#undef IS_IN_libpthread +#undef USE___THREAD + #include #include #include @@ -5,8 +14,6 @@ #include #include -#include "pt-machine.h" - #define N 4 -- 2.7.4