(linenum→info "unix/slp.c:2238")

glibc/2.7/csu/libc-tls.c

    1: /* Initialization code for TLS in statically linked application.
    2:    Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
    3:    This file is part of the GNU C Library.
    4: 
    5:    The GNU C Library is free software; you can redistribute it and/or
    6:    modify it under the terms of the GNU Lesser General Public
    7:    License as published by the Free Software Foundation; either
    8:    version 2.1 of the License, or (at your option) any later version.
    9: 
   10:    The GNU C Library is distributed in the hope that it will be useful,
   11:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   12:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   13:    Lesser General Public License for more details.
   14: 
   15:    You should have received a copy of the GNU Lesser General Public
   16:    License along with the GNU C Library; if not, write to the Free
   17:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   18:    02111-1307 USA.  */
   19: 
   20: #include <errno.h>
   21: #include <ldsodefs.h>
   22: #include <tls.h>
   23: #include <unistd.h>
   24: #include <stdio.h>
   25: #include <sys/param.h>
   26: 
   27: 
   28: #ifdef SHARED
   29:  #error makefile bug, this file is for static only
   30: #endif
   31: 
   32: extern ElfW(Phdr) *_dl_phdr;
   33: extern size_t _dl_phnum;
   34: 
   35: 
   36: static dtv_t static_dtv[2 + TLS_SLOTINFO_SURPLUS];
   37: 
   38: 
   39: static struct
   40: {
   41:   struct dtv_slotinfo_list si;
   42:   /* The dtv_slotinfo_list data structure does not include the actual
   43:      information since it is defined as an array of size zero.  We define
   44:      here the necessary entries.  Note that it is not important whether
   45:      there is padding or not since we will always access the information
   46:      through the 'si' element.  */
   47:   struct dtv_slotinfo info[2 + TLS_SLOTINFO_SURPLUS];
   48: } static_slotinfo;
   49: 
   50: /* Fake link map for the application.  */
   51: static struct link_map static_map;
   52: 
   53: 
   54: /* Highest dtv index currently needed.  */
   55: size_t _dl_tls_max_dtv_idx;
   56: /* Flag signalling whether there are gaps in the module ID allocation.  */
   57: bool _dl_tls_dtv_gaps;
   58: /* Information about the dtv slots.  */
   59: struct dtv_slotinfo_list *_dl_tls_dtv_slotinfo_list;
   60: /* Number of modules in the static TLS block.  */
   61: size_t _dl_tls_static_nelem;
   62: /* Size of the static TLS block.  Giving this initialized value
   63:    preallocates some surplus bytes in the static TLS area.  */
   64: size_t _dl_tls_static_size = 2048;
   65: /* Size actually allocated in the static TLS block.  */
   66: size_t _dl_tls_static_used;
   67: /* Alignment requirement of the static TLS block.  */
   68: size_t _dl_tls_static_align;
   69: 
   70: /* Generation counter for the dtv.  */
   71: size_t _dl_tls_generation;
   72: 
   73: 
   74: /* Additional definitions needed by TLS initialization.  */
   75: #ifdef TLS_INIT_HELPER
   76: TLS_INIT_HELPER
   77: #endif
   78: 
   79: static inline void
   80: init_slotinfo (void)
   81: {
   82:   /* Create the slotinfo list.  */
   83:   static_slotinfo.si.len = (((char *) (&static_slotinfo + 1)
   84:                              - (char *) &static_slotinfo.si.slotinfo[0])
   85:                             / sizeof static_slotinfo.si.slotinfo[0]);
   86:   // static_slotinfo.si.next = NULL;    already zero
   87: 
   88:   /* The slotinfo list.  Will be extended by the code doing dynamic
   89:      linking.  */
   90:   GL(dl_tls_max_dtv_idx) = 1;
   91:   GL(dl_tls_dtv_slotinfo_list) = &static_slotinfo.si;
   92: }
   93: 
   94: static inline void
   95: init_static_tls (size_t memsz, size_t align)
   96: {
   97:   /* That is the size of the TLS memory for this object.  The initialized
   98:      value of _dl_tls_static_size is provided by dl-open.c to request some
   99:      surplus that permits dynamic loading of modules with IE-model TLS.  */
  100:   GL(dl_tls_static_size) = roundup (memsz + GL(dl_tls_static_size),
  101:                                     TLS_TCB_ALIGN);
  102:   GL(dl_tls_static_used) = memsz;
  103:   /* The alignment requirement for the static TLS block.  */
  104:   GL(dl_tls_static_align) = align;
  105:   /* Number of elements in the static TLS block.  */
  106:   GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx);
  107: }
  108: 
  109: void
  110: __libc_setup_tls (size_t tcbsize, size_t tcbalign)
  111: {
  112:   void *tlsblock;
  113:   size_t memsz = 0;
  114:   size_t filesz = 0;
  115:   void *initimage = NULL;
  116:   size_t align = 0;
  117:   size_t max_align = tcbalign;
  118:   size_t tcb_offset;
  119:   ElfW(Phdr) *phdr;
  120: 
  121:   /* Look through the TLS segment if there is any.  */
  122:   if (_dl_phdr != NULL)
  123:     for (phdr = _dl_phdr; phdr < &_dl_phdr[_dl_phnum]; ++phdr)
  124:       if (phdr->p_type == PT_TLS)
  125:         {
  126:           /* Remember the values we need.  */
  127:           memsz = phdr->p_memsz;
  128:           filesz = phdr->p_filesz;
  129:           initimage = (void *) phdr->p_vaddr;
  130:           align = phdr->p_align;
  131:           if (phdr->p_align > max_align)
  132:             max_align = phdr->p_align;
  133:           break;
  134:         }
  135: 
  136:   /* We have to set up the TCB block which also (possibly) contains
  137:      'errno'.  Therefore we avoid 'malloc' which might touch 'errno'.
  138:      Instead we use 'sbrk' which would only uses 'errno' if it fails.
  139:      In this case we are right away out of memory and the user gets
  140:      what she/he deserves.
  141: 
  142:      The initialized value of _dl_tls_static_size is provided by dl-open.c
  143:      to request some surplus that permits dynamic loading of modules with
  144:      IE-model TLS.  */
  145: #if TLS_TCB_AT_TP
  146:   tcb_offset = roundup (memsz + GL(dl_tls_static_size), tcbalign);
  147:   tlsblock = __sbrk (tcb_offset + tcbsize + max_align);
  148: #elif TLS_DTV_AT_TP
  149:   tcb_offset = roundup (tcbsize, align ?: 1);
  150:   tlsblock = __sbrk (tcb_offset + memsz + max_align
  151:                      + TLS_PRE_TCB_SIZE + GL(dl_tls_static_size));
  152:   tlsblock += TLS_PRE_TCB_SIZE;
  153: #else
  154:   /* In case a model with a different layout for the TCB and DTV
  155:      is defined add another #elif here and in the following #ifs.  */
  156: # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
  157: #endif
  158: 
  159:   /* Align the TLS block.  */
  160:   tlsblock = (void *) (((uintptr_t) tlsblock + max_align - 1)
  161:                        & ~(max_align - 1));
  162: 
  163:   /* Initialize the dtv.  [0] is the length, [1] the generation counter.  */
  164:   static_dtv[0].counter = (sizeof (static_dtv) / sizeof (static_dtv[0])) - 2;
  165:   // static_dtv[1].counter = 0;         would be needed if not already done
  166: 
  167:   /* Initialize the TLS block.  */
  168: #if TLS_TCB_AT_TP
  169:   static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset
  170:                                - roundup (memsz, align ?: 1));
  171:   static_map.l_tls_offset = roundup (memsz, align ?: 1);
  172: #elif TLS_DTV_AT_TP
  173:   static_dtv[2].pointer.val = (char *) tlsblock + tcb_offset;
  174:   static_map.l_tls_offset = tcb_offset;
  175: #else
  176: # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
  177: #endif
  178:   static_dtv[2].pointer.is_static = true;
  179:   /* sbrk gives us zero'd memory, so we don't need to clear the remainder.  */
  180:   memcpy (static_dtv[2].pointer.val, initimage, filesz);
  181: 
  182:   /* Install the pointer to the dtv.  */
  183: 
  184:   /* Initialize the thread pointer.  */
  185: #if TLS_TCB_AT_TP
  186:   INSTALL_DTV ((char *) tlsblock + tcb_offset, static_dtv);
  187: 
  188:   const char *lossage = TLS_INIT_TP ((char *) tlsblock + tcb_offset, 0);
  189: #elif TLS_DTV_AT_TP
  190:   INSTALL_DTV (tlsblock, static_dtv);
  191:   const char *lossage = TLS_INIT_TP (tlsblock, 0);
  192: #else
  193: # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
  194: #endif
  195:   if (__builtin_expect (lossage != NULL, 0))
  196:     __libc_fatal (lossage);
  197: 
  198:   /* We have to create a fake link map which normally would be created
  199:      by the dynamic linker.  It just has to have enough information to
  200:      make the TLS routines happy.  */
  201:   static_map.l_tls_align = align;
  202:   static_map.l_tls_blocksize = memsz;
  203:   static_map.l_tls_initimage = initimage;
  204:   static_map.l_tls_initimage_size = filesz;
  205:   static_map.l_type = lt_executable;
  206:   static_map.l_tls_modid = 1;
  207: 
  208:   init_slotinfo ();
  209:   // static_slotinfo.si.slotinfo[1].gen = 0; already zero
  210:   static_slotinfo.si.slotinfo[1].map = &static_map;
  211: 
  212:   memsz = roundup (memsz, align ?: 1);
  213: 
  214: #if TLS_TCB_AT_TP
  215:   memsz += tcbsize;
  216: #elif TLS_DTV_AT_TP
  217:   memsz += tcb_offset;
  218: #endif
  219: 
  220:   init_static_tls (memsz, MAX (TLS_TCB_ALIGN, max_align));
  221: }
  222: 
  223: /* This is called only when the data structure setup was skipped at startup,
  224:    when there was no need for it then.  Now we have dynamically loaded
  225:    something needing TLS, or libpthread needs it.  */
  226: int
  227: internal_function
  228: _dl_tls_setup (void)
  229: {
  230:   init_slotinfo ();
  231:   init_static_tls (
  232: #if TLS_TCB_AT_TP
  233:                    TLS_TCB_SIZE,
  234: #else
  235:                    0,
  236: #endif
  237:                    TLS_TCB_ALIGN);
  238:   return 0;
  239: }
  240: 
  241: 
  242: /* This is the minimal initialization function used when libpthread is
  243:    not used.  */
  244: void
  245: __attribute__ ((weak))
  246: __pthread_initialize_minimal (void)
  247: {
  248:   __libc_setup_tls (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN);
  249: }
Syntax (Markdown)