]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Revert "Remove last use of USE___THREAD"
authorUlrich Drepper <drepper@gmail.com>
Mon, 12 Sep 2011 20:20:40 +0000 (16:20 -0400)
committerUlrich Drepper <drepper@gmail.com>
Mon, 12 Sep 2011 20:20:40 +0000 (16:20 -0400)
This reverts commit de82006d43e198fd162807c9adc720c7ebd728a3.

Conflicts:

ChangeLog

ChangeLog
elf/rtld.c

index 8ec914fc8e2ac61b82898e14778445977c7a32fc..40660b8153b2b33da34b0fee287b365abc293ecb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -5,8 +5,6 @@
        * sysdeps/unix/sysv/linux/sparc/bits/socket.h (__cmsg_nxthdr):
        Likewise.
 
-       * elf/rtld.c: Remove use of USE___THREAD.
-
 2011-09-11  Andreas Schwab  <schwab@linux-m68k.org>
 
        * elf/Makefile (gen-ldd): Prepend $(..) to $(ldd-rewrite-script)
index 0af932579a267ac0009a18070b696ca71948746f..b3959a34d06c2ce53a6d335eb48be0eafcf17ea2 100644 (file)
@@ -306,9 +306,21 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
   GL(dl_rtld_map).l_text_end = (ElfW(Addr)) _etext;
   /* Copy the TLS related data if necessary.  */
 #ifndef DONT_USE_BOOTSTRAP_MAP
-# if NO_TLS_OFFSET != 0
+# if USE___THREAD
+  assert (info->l.l_tls_modid != 0);
+  GL(dl_rtld_map).l_tls_blocksize = info->l.l_tls_blocksize;
+  GL(dl_rtld_map).l_tls_align = info->l.l_tls_align;
+  GL(dl_rtld_map).l_tls_firstbyte_offset = info->l.l_tls_firstbyte_offset;
+  GL(dl_rtld_map).l_tls_initimage_size = info->l.l_tls_initimage_size;
+  GL(dl_rtld_map).l_tls_initimage = info->l.l_tls_initimage;
+  GL(dl_rtld_map).l_tls_offset = info->l.l_tls_offset;
+  GL(dl_rtld_map).l_tls_modid = 1;
+# else
+#  if NO_TLS_OFFSET != 0
   GL(dl_rtld_map).l_tls_offset = NO_TLS_OFFSET;
+#  endif
 # endif
+
 #endif
 
 #if HP_TIMING_AVAIL
@@ -390,6 +402,9 @@ _dl_start (void *arg)
        ++cnt)
     bootstrap_map.l_info[cnt] = 0;
 # endif
+# if USE___THREAD
+  bootstrap_map.l_tls_modid = 0;
+# endif
 #endif
 
   /* Figure out the run-time load address of the dynamic linker itself.  */
@@ -403,6 +418,123 @@ _dl_start (void *arg)
   bootstrap_map.l_tls_offset = NO_TLS_OFFSET;
 #endif
 
+  /* Get the dynamic linker's own program header.  First we need the ELF
+     file header.  The `_begin' symbol created by the linker script points
+     to it.  When we have something like GOTOFF relocs, we can use a plain
+     reference to find the runtime address.  Without that, we have to rely
+     on the `l_addr' value, which is not the value we want when prelinked.  */
+#if USE___THREAD
+  dtv_t initdtv[3];
+  ElfW(Ehdr) *ehdr
+# ifdef DONT_USE_BOOTSTRAP_MAP
+    = (ElfW(Ehdr) *) &_begin;
+# else
+#  error This will not work with prelink.
+    = (ElfW(Ehdr) *) bootstrap_map.l_addr;
+# endif
+  ElfW(Phdr) *phdr = (ElfW(Phdr) *) ((void *) ehdr + ehdr->e_phoff);
+  size_t cnt = ehdr->e_phnum;  /* PT_TLS is usually the last phdr.  */
+  while (cnt-- > 0)
+    if (phdr[cnt].p_type == PT_TLS)
+      {
+       void *tlsblock;
+       size_t max_align = MAX (TLS_INIT_TCB_ALIGN, phdr[cnt].p_align);
+       char *p;
+
+       bootstrap_map.l_tls_blocksize = phdr[cnt].p_memsz;
+       bootstrap_map.l_tls_align = phdr[cnt].p_align;
+       if (phdr[cnt].p_align == 0)
+         bootstrap_map.l_tls_firstbyte_offset = 0;
+       else
+         bootstrap_map.l_tls_firstbyte_offset = (phdr[cnt].p_vaddr
+                                                 & (phdr[cnt].p_align - 1));
+       assert (bootstrap_map.l_tls_blocksize != 0);
+       bootstrap_map.l_tls_initimage_size = phdr[cnt].p_filesz;
+       bootstrap_map.l_tls_initimage = (void *) (bootstrap_map.l_addr
+                                                 + phdr[cnt].p_vaddr);
+
+       /* We can now allocate the initial TLS block.  This can happen
+          on the stack.  We'll get the final memory later when we
+          know all about the various objects loaded at startup
+          time.  */
+# if TLS_TCB_AT_TP
+       tlsblock = alloca (roundup (bootstrap_map.l_tls_blocksize,
+                                   TLS_INIT_TCB_ALIGN)
+                          + TLS_INIT_TCB_SIZE
+                          + max_align);
+# elif TLS_DTV_AT_TP
+       tlsblock = alloca (roundup (TLS_INIT_TCB_SIZE,
+                                   bootstrap_map.l_tls_align)
+                          + bootstrap_map.l_tls_blocksize
+                          + max_align);
+# else
+       /* In case a model with a different layout for the TCB and DTV
+          is defined add another #elif here and in the following #ifs.  */
+#  error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+# endif
+       /* Align the TLS block.  */
+       tlsblock = (void *) (((uintptr_t) tlsblock + max_align - 1)
+                            & ~(max_align - 1));
+
+       /* Initialize the dtv.  [0] is the length, [1] the generation
+          counter.  */
+       initdtv[0].counter = 1;
+       initdtv[1].counter = 0;
+
+       /* Initialize the TLS block.  */
+# if TLS_TCB_AT_TP
+       initdtv[2].pointer = tlsblock;
+# elif TLS_DTV_AT_TP
+       bootstrap_map.l_tls_offset = roundup (TLS_INIT_TCB_SIZE,
+                                             bootstrap_map.l_tls_align);
+       initdtv[2].pointer = (char *) tlsblock + bootstrap_map.l_tls_offset;
+# else
+#  error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+# endif
+       p = __mempcpy (initdtv[2].pointer, bootstrap_map.l_tls_initimage,
+                      bootstrap_map.l_tls_initimage_size);
+# ifdef HAVE_BUILTIN_MEMSET
+       __builtin_memset (p, '\0', (bootstrap_map.l_tls_blocksize
+                                   - bootstrap_map.l_tls_initimage_size));
+# else
+       {
+         size_t remaining = (bootstrap_map.l_tls_blocksize
+                             - bootstrap_map.l_tls_initimage_size);
+         while (remaining-- > 0)
+           *p++ = '\0';
+       }
+# endif
+
+       /* Install the pointer to the dtv.  */
+
+       /* Initialize the thread pointer.  */
+# if TLS_TCB_AT_TP
+       bootstrap_map.l_tls_offset
+         = roundup (bootstrap_map.l_tls_blocksize, TLS_INIT_TCB_ALIGN);
+
+       INSTALL_DTV ((char *) tlsblock + bootstrap_map.l_tls_offset,
+                    initdtv);
+
+       const char *lossage = TLS_INIT_TP ((char *) tlsblock
+                                          + bootstrap_map.l_tls_offset, 0);
+# elif TLS_DTV_AT_TP
+       INSTALL_DTV (tlsblock, initdtv);
+       const char *lossage = TLS_INIT_TP (tlsblock, 0);
+# else
+#  error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+# endif
+       if (__builtin_expect (lossage != NULL, 0))
+         _dl_fatal_printf ("cannot set up thread-local storage: %s\n",
+                           lossage);
+
+       /* So far this is module number one.  */
+       bootstrap_map.l_tls_modid = 1;
+
+       /* There can only be one PT_TLS entry.  */
+       break;
+      }
+#endif /* USE___THREAD */
+
 #ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
   ELF_MACHINE_BEFORE_RTLD_RELOC (bootstrap_map.l_info);
 #endif
@@ -647,7 +779,7 @@ cannot allocate TLS data structures for initial thread");
 
   /* And finally install it for the main thread.  If ld.so itself uses
      TLS we know the thread pointer was initialized earlier.  */
-  const char *lossage = TLS_INIT_TP (tcbp, 0);
+  const char *lossage = TLS_INIT_TP (tcbp, USE___THREAD);
   if (__builtin_expect (lossage != NULL, 0))
     _dl_fatal_printf ("cannot set up thread-local storage: %s\n", lossage);
   tls_init_tp_called = true;
@@ -2178,7 +2310,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
      TLS we know the thread pointer was initialized earlier.  */
   if (! tls_init_tp_called)
     {
-      const char *lossage = TLS_INIT_TP (tcbp, 0);
+      const char *lossage = TLS_INIT_TP (tcbp, USE___THREAD);
       if (__builtin_expect (lossage != NULL, 0))
        _dl_fatal_printf ("cannot set up thread-local storage: %s\n",
                          lossage);