]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - csu/libc-tls.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / csu / libc-tls.c
index 3544e396dae381669b1c3667ab74024c6a7f7c4d..64d177955feb2ad083c1a2bc3265efaadd58cc07 100644 (file)
@@ -1,5 +1,5 @@
 /* Initialization code for TLS in statically linked application.
-   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2002-2015 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -13,9 +13,8 @@
    Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
 
 #include <errno.h>
 #include <ldsodefs.h>
  #error makefile bug, this file is for static only
 #endif
 
-#ifdef USE_TLS
-extern ElfW(Phdr) *_dl_phdr;
-extern size_t _dl_phnum;
-
-
-static dtv_t static_dtv[2 + TLS_SLOTINFO_SURPLUS];
+dtv_t _dl_static_dtv[2 + TLS_SLOTINFO_SURPLUS];
 
 
 static struct
@@ -48,9 +42,6 @@ static struct
   struct dtv_slotinfo info[2 + TLS_SLOTINFO_SURPLUS];
 } static_slotinfo;
 
-/* Fake link map for the application.  */
-static struct link_map static_map;
-
 
 /* Highest dtv index currently needed.  */
 size_t _dl_tls_max_dtv_idx;
@@ -77,7 +68,7 @@ size_t _dl_tls_generation;
 TLS_INIT_HELPER
 #endif
 
-static inline void
+static void
 init_slotinfo (void)
 {
   /* Create the slotinfo list.  */
@@ -92,7 +83,7 @@ init_slotinfo (void)
   GL(dl_tls_dtv_slotinfo_list) = &static_slotinfo.si;
 }
 
-static inline void
+static void
 init_static_tls (size_t memsz, size_t align)
 {
   /* That is the size of the TLS memory for this object.  The initialized
@@ -100,6 +91,9 @@ init_static_tls (size_t memsz, size_t align)
      surplus that permits dynamic loading of modules with IE-model TLS.  */
   GL(dl_tls_static_size) = roundup (memsz + GL(dl_tls_static_size),
                                    TLS_TCB_ALIGN);
+#if TLS_TCB_AT_TP
+  GL(dl_tls_static_size) += TLS_TCB_SIZE;
+#endif
   GL(dl_tls_static_used) = memsz;
   /* The alignment requirement for the static TLS block.  */
   GL(dl_tls_static_align) = align;
@@ -117,7 +111,7 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
   size_t align = 0;
   size_t max_align = tcbalign;
   size_t tcb_offset;
-  ElfW(Phdr) *phdr;
+  const ElfW(Phdr) *phdr;
 
   /* Look through the TLS segment if there is any.  */
   if (_dl_phdr != NULL)
@@ -143,80 +137,78 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
      The initialized value of _dl_tls_static_size is provided by dl-open.c
      to request some surplus that permits dynamic loading of modules with
      IE-model TLS.  */
-# if TLS_TCB_AT_TP
+#if TLS_TCB_AT_TP
   tcb_offset = roundup (memsz + GL(dl_tls_static_size), tcbalign);
   tlsblock = __sbrk (tcb_offset + tcbsize + max_align);
-# elif TLS_DTV_AT_TP
+#elif TLS_DTV_AT_TP
   tcb_offset = roundup (tcbsize, align ?: 1);
   tlsblock = __sbrk (tcb_offset + memsz + max_align
                     + TLS_PRE_TCB_SIZE + GL(dl_tls_static_size));
   tlsblock += TLS_PRE_TCB_SIZE;
-# else
+#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
+# 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.  */
-  static_dtv[0].counter = (sizeof (static_dtv) / sizeof (static_dtv[0])) - 2;
-  // static_dtv[1].counter = 0;                would be needed if not already done
+  _dl_static_dtv[0].counter = (sizeof (_dl_static_dtv) / sizeof (_dl_static_dtv[0])) - 2;
+  // _dl_static_dtv[1].counter = 0;            would be needed if not already done
+
+  struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
 
   /* Initialize the TLS block.  */
-# if TLS_TCB_AT_TP
-  static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset
+#if TLS_TCB_AT_TP
+  _dl_static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset
                               - roundup (memsz, align ?: 1));
-  static_map.l_tls_offset = roundup (memsz, align ?: 1);
-# elif TLS_DTV_AT_TP
-  static_dtv[2].pointer.val = (char *) tlsblock + tcb_offset;
-  static_map.l_tls_offset = tcb_offset;
-# else
-#  error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
-# endif
-  static_dtv[2].pointer.is_static = true;
+  main_map->l_tls_offset = roundup (memsz, align ?: 1);
+#elif TLS_DTV_AT_TP
+  _dl_static_dtv[2].pointer.val = (char *) tlsblock + tcb_offset;
+  main_map->l_tls_offset = tcb_offset;
+#else
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+#endif
+  _dl_static_dtv[2].pointer.is_static = true;
   /* sbrk gives us zero'd memory, so we don't need to clear the remainder.  */
-  memcpy (static_dtv[2].pointer.val, initimage, filesz);
+  memcpy (_dl_static_dtv[2].pointer.val, initimage, filesz);
 
   /* Install the pointer to the dtv.  */
 
   /* Initialize the thread pointer.  */
-# if TLS_TCB_AT_TP
-  INSTALL_DTV ((char *) tlsblock + tcb_offset, static_dtv);
-
-  const char *lossage = TLS_INIT_TP ((char *) tlsblock + tcb_offset, 0);
-# elif TLS_DTV_AT_TP
-  INSTALL_DTV (tlsblock, static_dtv);
-  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 TLS_TCB_AT_TP
+  INSTALL_DTV ((char *) tlsblock + tcb_offset, _dl_static_dtv);
+
+  const char *lossage = TLS_INIT_TP ((char *) tlsblock + tcb_offset);
+#elif TLS_DTV_AT_TP
+  INSTALL_DTV (tlsblock, _dl_static_dtv);
+  const char *lossage = TLS_INIT_TP (tlsblock);
+#else
+# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+#endif
   if (__builtin_expect (lossage != NULL, 0))
     __libc_fatal (lossage);
 
-  /* We have to create a fake link map which normally would be created
-     by the dynamic linker.  It just has to have enough information to
-     make the TLS routines happy.  */
-  static_map.l_tls_align = align;
-  static_map.l_tls_blocksize = memsz;
-  static_map.l_tls_initimage = initimage;
-  static_map.l_tls_initimage_size = filesz;
-  static_map.l_type = lt_executable;
-  static_map.l_tls_modid = 1;
+  /* Update the executable's link map with enough information to make
+     the TLS routines happy.  */
+  main_map->l_tls_align = align;
+  main_map->l_tls_blocksize = memsz;
+  main_map->l_tls_initimage = initimage;
+  main_map->l_tls_initimage_size = filesz;
+  main_map->l_tls_modid = 1;
 
   init_slotinfo ();
   // static_slotinfo.si.slotinfo[1].gen = 0; already zero
-  static_slotinfo.si.slotinfo[1].map = &static_map;
+  static_slotinfo.si.slotinfo[1].map = main_map;
 
   memsz = roundup (memsz, align ?: 1);
 
-# if TLS_TCB_AT_TP
-  memsz += tcbsize;
-# elif TLS_DTV_AT_TP
+#if TLS_DTV_AT_TP
   memsz += tcb_offset;
-# endif
+#endif
 
   init_static_tls (memsz, MAX (TLS_TCB_ALIGN, max_align));
 }
@@ -230,11 +222,11 @@ _dl_tls_setup (void)
 {
   init_slotinfo ();
   init_static_tls (
-# if TLS_TCB_AT_TP
+#if TLS_TCB_AT_TP
                   TLS_TCB_SIZE,
-# else
+#else
                   0,
-# endif
+#endif
                   TLS_TCB_ALIGN);
   return 0;
 }
@@ -248,16 +240,3 @@ __pthread_initialize_minimal (void)
 {
   __libc_setup_tls (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN);
 }
-
-#elif defined NONTLS_INIT_TP
-
-/* This is the minimal initialization function used when libpthread is
-   not used.  */
-void
-__attribute__ ((weak))
-__pthread_initialize_minimal (void)
-{
-  NONTLS_INIT_TP;
-}
-
-#endif