about summary refs log tree commit diff
path: root/elf/rtld.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/rtld.c')
-rw-r--r--elf/rtld.c101
1 files changed, 58 insertions, 43 deletions
diff --git a/elf/rtld.c b/elf/rtld.c
index a19fad24a4..2ebde4530a 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -309,14 +309,20 @@ _dl_start_final (void *arg, struct link_map *bootstrap_map_p,
 		'\0', (GL(dl_rtld_map).l_tls_blocksize
 		       - GL(dl_rtld_map).l_tls_initimage_size));
 
+	/* Install the pointer to the dtv.  */
+
 	/* Initialize the thread pointer.  */
 # if TLS_TCB_AT_TP
 	GL(dl_rtld_map).l_tls_offset
 	  = roundup (GL(dl_rtld_map).l_tls_blocksize, TLS_INIT_TCB_ALIGN);
-	TLS_INIT_TP ((char *) tlsblock + GL(dl_rtld_map).l_tls_offset,
+
+	INSTALL_DTV ((char *) tlsblock + GL(dl_rtld_map).l_tls_offset,
 		     initdtv);
+
+	TLS_INIT_TP ((char *) tlsblock + GL(dl_rtld_map).l_tls_offset);
 # elif TLS_DTV_AT_TP
-	TLS_INIT_TP (tlsblock, initdtv);
+	INSTALL_DTV (tlsblock, initdtv);
+	TLS_INIT_TP (tlsblock);
 # else
 #  error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
 # endif
@@ -477,6 +483,9 @@ dl_main (const ElfW(Phdr) *phdr,
   hp_timing_t stop;
   hp_timing_t diff;
 #endif
+#ifdef USE_TLS
+  void *tcbp;
+#endif
 
   /* Process the environment variable which control the behaviour.  */
   process_envvars (&mode);
@@ -1169,6 +1178,53 @@ of this helper program; chances are you did not intend to run this program.\n\
       _exit (0);
     }
 
+#ifdef USE_TLS
+  /* Now it is time to determine the layout of the static TLS block
+     and allocate it for the initial thread.  Note that we always
+     allocate the static block, we never defer it even if no
+     DF_STATIC_TLS bit is set.  The reason is that we know glibc will
+     use the static model.  First add the dynamic linker to the list
+     if it also uses TLS.  */
+  if (GL(dl_rtld_map).l_tls_blocksize != 0)
+    {
+      /* At to the list.  */
+      if (GL(dl_initimage_list) == NULL)
+	GL(dl_initimage_list) = GL(dl_rtld_map).l_tls_nextimage
+	  = GL(dl_rtld_map).l_tls_previmage = &GL(dl_rtld_map);
+	  else
+	    {
+	      GL(dl_rtld_map).l_tls_nextimage
+		= GL(dl_initimage_list)->l_tls_nextimage;
+	      GL(dl_rtld_map).l_tls_nextimage->l_tls_previmage
+		= &GL(dl_rtld_map);
+	      GL(dl_rtld_map).l_tls_previmage = GL(dl_initimage_list);
+	      GL(dl_rtld_map).l_tls_previmage->l_tls_nextimage
+		= &GL(dl_rtld_map);
+	      GL(dl_initimage_list) = &GL(dl_rtld_map);
+	    }
+
+      /* Assign a module ID.  */
+      GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
+    }
+
+  /* Computer the TLS offsets for the various blocks.  We call this
+     function even if none of the modules available at startup time
+     uses TLS to initialize some variables.  */
+    _dl_determine_tlsoffset (GL(dl_initimage_list));
+
+  /* Construct the static TLS block and the dtv for the initial
+     thread.  For some platforms this will include allocating memory
+     for the thread descriptor.  The memory for the TLS block will
+     never be freed.  It should be allocated accordingly.  The dtv
+     array can be changed if dynamic loading requires it.  */
+  tcbp = _dl_allocate_tls ();
+  if (tcbp == NULL)
+    _dl_fatal_printf ("cannot allocate TLS data structures for inital thread");
+
+  /* And finally install it for the main thread.  */
+  TLS_INIT_TP (tcbp);
+#endif
+
   if (GL(dl_loaded)->l_info [ADDRIDX (DT_GNU_LIBLIST)]
       && ! __builtin_expect (GL(dl_profile) != NULL, 0))
     {
@@ -1333,47 +1389,6 @@ of this helper program; chances are you did not intend to run this program.\n\
      we need it in the memory handling later.  */
   GL(dl_initial_searchlist) = *GL(dl_main_searchlist);
 
-#ifdef USE_TLS
-  /* Now it is time to determine the layout of the static TLS block
-     and allocate it for the initial thread.  Note that we always
-     allocate the static block, we never defer it even if no
-     DF_STATIC_TLS bit is set.  The reason is that we know glibc will
-     use the static model.  First add the dynamic linker to the list
-     if it also uses TLS.  */
-  if (GL(dl_rtld_map).l_tls_blocksize != 0)
-    {
-      /* At to the list.  */
-      if (GL(dl_initimage_list) == NULL)
-	GL(dl_initimage_list) = GL(dl_rtld_map).l_tls_nextimage
-	  = GL(dl_rtld_map).l_tls_previmage = &GL(dl_rtld_map);
-	  else
-	    {
-	      GL(dl_rtld_map).l_tls_nextimage
-		= GL(dl_initimage_list)->l_tls_nextimage;
-	      GL(dl_rtld_map).l_tls_nextimage->l_tls_previmage
-		= &GL(dl_rtld_map);
-	      GL(dl_rtld_map).l_tls_previmage = GL(dl_initimage_list);
-	      GL(dl_rtld_map).l_tls_previmage->l_tls_nextimage
-		= &GL(dl_rtld_map);
-	      GL(dl_initimage_list) = &GL(dl_rtld_map);
-	    }
-
-      /* Assign a module ID.  */
-      GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
-    }
-
-  if (GL(dl_initimage_list) != NULL)
-    /* This means we actually have some modules which use TLS.
-       Computer the TLS offsets for the various blocks.  */
-    _dl_determine_tlsoffset (GL(dl_initimage_list)->l_tls_nextimage);
-
-  /* Construct the static TLS block and the dtv for the initial
-     thread.  For some platforms this will include allocating memory
-     for the thread descriptor.  The memory for the TLS block will
-     never be freed.  It should be allocated accordingly.  The dtv
-     array can be changed if dynamic loading requires it.  */
-#endif
-
   {
     /* Initialize _r_debug.  */
     struct r_debug *r = _dl_debug_initialize (GL(dl_rtld_map).l_addr);