about summary refs log tree commit diff
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-close.c17
-rw-r--r--elf/dl-load.c24
-rw-r--r--elf/rtld.c16
-rw-r--r--elf/tst-tls4.c8
-rw-r--r--elf/tst-tls5.c9
-rw-r--r--elf/tst-tls6.c9
-rw-r--r--elf/tst-tls7.c9
-rw-r--r--elf/tst-tls8.c9
-rw-r--r--elf/tst-tls9.c9
9 files changed, 92 insertions, 18 deletions
diff --git a/elf/dl-close.c b/elf/dl-close.c
index 632f8ba9fc..b5c2841d61 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 3452c0b1b4..c550204ac5 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 350cc700b5..6e20e15fff 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 f92ee53ce5..32ec147420 100644
--- a/elf/tst-tls4.c
+++ b/elf/tst-tls4.c
@@ -4,6 +4,14 @@
 
 #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
diff --git a/elf/tst-tls5.c b/elf/tst-tls5.c
index a571d2cd3f..c10015d94d 100644
--- a/elf/tst-tls5.c
+++ b/elf/tst-tls5.c
@@ -4,6 +4,15 @@
 
 #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
diff --git a/elf/tst-tls6.c b/elf/tst-tls6.c
index 2c015efebb..3c5c7aae4e 100644
--- a/elf/tst-tls6.c
+++ b/elf/tst-tls6.c
@@ -5,6 +5,15 @@
 #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
diff --git a/elf/tst-tls7.c b/elf/tst-tls7.c
index 4f785fe78e..77d2016d08 100644
--- a/elf/tst-tls7.c
+++ b/elf/tst-tls7.c
@@ -5,6 +5,15 @@
 #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
diff --git a/elf/tst-tls8.c b/elf/tst-tls8.c
index e300bc53d8..7444c261ec 100644
--- a/elf/tst-tls8.c
+++ b/elf/tst-tls8.c
@@ -5,6 +5,15 @@
 #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
diff --git a/elf/tst-tls9.c b/elf/tst-tls9.c
index cd958e47fb..a679efcd63 100644
--- a/elf/tst-tls9.c
+++ b/elf/tst-tls9.c
@@ -5,6 +5,15 @@
 #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