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-12-02 Roland McGrath <roland@redhat.com>
+
+ * 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 <bruno@clisp.org>
* iconv/gconv.h (__gconv_btowc_fct): New typedef.
}
#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
}
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;
/* 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;
}
/* 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;
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
#include <tls.h>
+#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
#include <tls.h>
+#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
#include <link.h>
#include <tls.h>
+#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
#include <link.h>
#include <tls.h>
+#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
#include <link.h>
#include <tls.h>
+#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
#include <link.h>
#include <tls.h>
+#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
#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
# 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 }; \
({ 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 */
+/* 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 <tls.h>. So kludge around it. */
+
+#define IS_IN_libpthread
+#include <tls.h>
+#undef IS_IN_libpthread
+#undef USE___THREAD
+
#include <errno.h>
#include <error.h>
#include <pthread.h>
#include <stdlib.h>
#include <ucontext.h>
-#include "pt-machine.h"
-
#define N 4