Define _dl_tls_static_used.
[kopensolaris-gnu/glibc.git] / sysdeps / generic / libc-tls.c
1 /* Initialization code for TLS in statically linked application.
2    Copyright (C) 2002 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
25 #ifdef SHARED
26  #error makefile bug, this file is for static only
27 #endif
28
29 #ifdef USE_TLS
30 extern ElfW(Phdr) *_dl_phdr;
31 extern size_t _dl_phnum;
32
33
34 /* DTV with just one element plus overhead.  */
35 static dtv_t static_dtv[3];
36
37
38 static struct
39 {
40   struct dtv_slotinfo_list si;
41   /* The dtv_slotinfo_list data structure does not include the actual
42      information since it is defined as an array of size zero.  We define
43      here the necessary entries.  Note that it is not important whether
44      there is padding or not since we will always access the information
45      through the 'si' element.  */
46   struct dtv_slotinfo info[2 + TLS_SLOTINFO_SURPLUS];
47 } static_slotinfo;
48
49 /* Fake link map for the application.  */
50 static struct link_map static_map;
51
52
53 /* Highest dtv index currently needed.  */
54 size_t _dl_tls_max_dtv_idx;
55 /* Flag signalling whether there are gaps in the module ID allocation.  */
56 bool _dl_tls_dtv_gaps;
57 /* Information about the dtv slots.  */
58 struct dtv_slotinfo_list *_dl_tls_dtv_slotinfo_list;
59 /* Number of modules in the static TLS block.  */
60 size_t _dl_tls_static_nelem;
61 /* Size of the static TLS block.  */
62 size_t _dl_tls_static_size;
63 /* Size actually allocated in the static TLS block.  */
64 size_t _dl_tls_static_used;
65 /* Alignment requirement of the static TLS block.  */
66 size_t _dl_tls_static_align;
67
68 /* Generation counter for the dtv.  */
69 size_t _dl_tls_generation;
70
71
72 /* Additional definitions needed by TLS initialization.  */
73 #ifdef TLS_INIT_HELPER
74 TLS_INIT_HELPER
75 #endif
76
77
78 void
79 __libc_setup_tls (size_t tcbsize, size_t tcbalign)
80 {
81   void *tlsblock;
82   size_t memsz = 0;
83   size_t filesz = 0;
84   void *initimage = NULL;
85   size_t align = 0;
86   size_t max_align = tcbalign;
87   size_t tcb_offset;
88   ElfW(Phdr) *phdr;
89
90   /* Look through the TLS segment if there is any.  */
91   if (_dl_phdr != NULL)
92     for (phdr = _dl_phdr; phdr < &_dl_phdr[_dl_phnum]; ++phdr)
93       if (phdr->p_type == PT_TLS)
94         {
95           /* Remember the values we need.  */
96           memsz = phdr->p_memsz;
97           filesz = phdr->p_filesz;
98           initimage = (void *) phdr->p_vaddr;
99           align = phdr->p_align;
100           if (phdr->p_align > max_align)
101             max_align = phdr->p_align;
102           break;
103         }
104
105   if (memsz == 0 && tcbsize == 0)
106     /* We do not need a TLS block and no thread descriptor.  */
107     return;
108
109   /* We have to set up the TCB block which also (possibly) contains
110      'errno'.  Therefore we avoid 'malloc' which might touch 'errno'.
111      Instead we use 'sbrk' which would only uses 'errno' if it fails.
112      In this case we are right away out of memory and the user gets
113      what she/he deserves.  */
114 # if TLS_TCB_AT_TP
115   tlsblock = __sbrk (roundup (memsz, tcbalign) + tcbsize + max_align);
116 # elif TLS_DTV_AT_TP
117   tlsblock = __sbrk (roundup (tcbsize, align) + memsz + max_align);
118 # else
119   /* In case a model with a different layout for the TCB and DTV
120      is defined add another #elif here and in the following #ifs.  */
121 #  error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
122 # endif
123
124   /* Align the TLS block.  */
125   tlsblock = (void *) (((uintptr_t) tlsblock + max_align - 1)
126                        & ~(max_align - 1));
127
128   /* Initialize the dtv.  [0] is the length, [1] the generation counter.  */
129   static_dtv[0].counter = 1;
130   // static_dtv[1].counter = 0;         would be needed if not already done
131
132   /* Initialize the TLS block.  */
133 # if TLS_TCB_AT_TP
134   static_dtv[2].pointer = tlsblock;
135 # elif TLS_DTV_AT_TP
136   tcb_offset = roundup (tcbsize, align);
137   static_dtv[2].pointer = (char *) tlsblock + tcb_offset;
138 # else
139 #  error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
140 # endif
141   memset (__mempcpy (static_dtv[2].pointer, initimage, filesz),
142           '\0', memsz - filesz);
143
144   /* Install the pointer to the dtv.  */
145
146   /* Initialize the thread pointer.  */
147 # if TLS_TCB_AT_TP
148   tcb_offset = roundup (memsz, tcbalign);
149
150   INSTALL_DTV ((char *) tlsblock + tcb_offset, static_dtv);
151
152   TLS_INIT_TP ((char *) tlsblock + tcb_offset, 0);
153 # elif TLS_DTV_AT_TP
154   INSTALL_DTV (tlsblock, static_dtv);
155   TLS_INIT_TP (tlsblock, 0);
156 # else
157 #  error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
158 # endif
159
160   /* We have to create a fake link map which normally would be created
161      by the dynamic linker.  It just has to have enough information to
162      make the TLS routines happy.  */
163   static_map.l_tls_align = align;
164   static_map.l_tls_blocksize = memsz;
165   static_map.l_tls_initimage = initimage;
166   static_map.l_tls_initimage_size = filesz;
167   static_map.l_tls_offset = tcb_offset;
168   static_map.l_type = lt_executable;
169   static_map.l_tls_modid = 1;
170
171   /* Create the slotinfo list.  */
172   static_slotinfo.si.len = (((char *) (&static_slotinfo + 1)
173                              - (char *) &static_slotinfo.si.slotinfo[0])
174                             / sizeof static_slotinfo.si.slotinfo[0]);
175   // static_slotinfo.si.next = NULL;    already zero
176
177   static_slotinfo.si.slotinfo[1].gen = 0;
178   static_slotinfo.si.slotinfo[1].map = &static_map;
179
180   /* The slotinfo list.  Will be extended by the code doing dynamic
181      linking.  */
182   GL(dl_tls_max_dtv_idx) = 1;
183   GL(dl_tls_dtv_slotinfo_list) = &static_slotinfo.si;
184
185   /* That is the size of the TLS memory for this object.  */
186   GL(dl_tls_static_size) = (roundup (memsz, align ?: 1)
187 # if TLS_TCB_AT_TP
188                             + tcbsize
189 # endif
190                             );
191   /* The alignment requirement for the static TLS block.  */
192   GL(dl_tls_static_align) = MAX (TLS_TCB_ALIGN, max_align);
193   /* Number of elements in the static TLS block.  */
194   GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx);
195 }
196
197
198 /* This is the minimal initialization function used when libpthread is
199    not used.  */
200 void
201 __attribute__ ((weak))
202 __pthread_initialize_minimal (void)
203 {
204   __libc_setup_tls (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN);
205 }
206 #endif