* elf/Makefile (tests): Substitute tests-vis-yes here.
[platform/upstream/glibc.git] / elf / dl-reloc.c
1 /* Relocate a shared object and resolve its references to other loaded objects.
2    Copyright (C) 1995-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 <libintl.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <ldsodefs.h>
25 #include <sys/mman.h>
26 #include <sys/param.h>
27 #include <sys/types.h>
28 #include "dynamic-link.h"
29
30 /* Statistics function.  */
31 #ifdef SHARED
32 # define bump_num_cache_relocations() ++GL(dl_num_cache_relocations)
33 #else
34 # define bump_num_cache_relocations() ((void) 0)
35 #endif
36
37
38 /* We are trying to perform a static TLS relocation in MAP, but it was
39    dynamically loaded.  This can only work if there is enough surplus in
40    the static TLS area already allocated for each running thread.  If this
41    object's TLS segment is too big to fit, we fail.  If it fits,
42    we set MAP->l_tls_offset and return.
43    This function intentionally does not return any value but signals error
44    directly, as static TLS should be rare and code handling it should
45    not be inlined as much as possible.  */
46 void
47 internal_function __attribute_noinline__
48 _dl_allocate_static_tls (struct link_map *map)
49 {
50   /* If we've already used the variable with dynamic access, or if the
51      alignment requirements are too high, fail.  */
52   if (map->l_tls_offset == FORCED_DYNAMIC_TLS_OFFSET
53       || map->l_tls_align > GL(dl_tls_static_align))
54     {
55     fail:
56       _dl_signal_error (0, map->l_name, NULL, N_("\
57 cannot allocate memory in static TLS block"));
58     }
59
60 #if TLS_TCB_AT_TP
61   size_t freebytes;
62   size_t n;
63   size_t blsize;
64
65   freebytes = GL(dl_tls_static_size) - GL(dl_tls_static_used) - TLS_TCB_SIZE;
66
67   blsize = map->l_tls_blocksize + map->l_tls_firstbyte_offset;
68   if (freebytes < blsize)
69     goto fail;
70
71   n = (freebytes - blsize) / map->l_tls_align;
72
73   size_t offset = GL(dl_tls_static_used) + (freebytes - n * map->l_tls_align
74                                             - map->l_tls_firstbyte_offset);
75
76   map->l_tls_offset = GL(dl_tls_static_used) = offset;
77 #elif TLS_DTV_AT_TP
78   size_t used;
79   size_t check;
80
81   size_t offset = roundup (GL(dl_tls_static_used), map->l_tls_align);
82   used = offset + map->l_tls_blocksize;
83   check = used;
84   /* dl_tls_static_used includes the TCB at the beginning.  */
85
86   if (check > GL(dl_tls_static_size))
87     goto fail;
88
89   map->l_tls_offset = offset;
90   GL(dl_tls_static_used) = used;
91 #else
92 # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
93 #endif
94
95   /* If the object is not yet relocated we cannot initialize the
96      static TLS region.  Delay it.  */
97   if (map->l_real->l_relocated)
98     {
99 #ifdef SHARED
100       if (__builtin_expect (THREAD_DTV()[0].counter != GL(dl_tls_generation),
101                             0))
102         /* Update the slot information data for at least the generation of
103            the DSO we are allocating data for.  */
104         (void) _dl_update_slotinfo (map->l_tls_modid);
105 #endif
106
107       GL(dl_init_static_tls) (map);
108     }
109   else
110     map->l_need_tls_init = 1;
111 }
112
113 /* Initialize static TLS area and DTV for current (only) thread.
114    libpthread implementations should provide their own hook
115    to handle all threads.  */
116 void
117 _dl_nothread_init_static_tls (struct link_map *map)
118 {
119 #if TLS_TCB_AT_TP
120   void *dest = (char *) THREAD_SELF - map->l_tls_offset;
121 #elif TLS_DTV_AT_TP
122   void *dest = (char *) THREAD_SELF + map->l_tls_offset + TLS_PRE_TCB_SIZE;
123 #else
124 # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
125 #endif
126
127   /* Fill in the DTV slot so that a later LD/GD access will find it.  */
128   dtv_t *dtv = THREAD_DTV ();
129   assert (map->l_tls_modid <= dtv[-1].counter);
130   dtv[map->l_tls_modid].pointer.val = dest;
131   dtv[map->l_tls_modid].pointer.is_static = true;
132
133   /* Initialize the memory.  */
134   memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
135           '\0', map->l_tls_blocksize - map->l_tls_initimage_size);
136 }
137
138
139 void
140 _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
141                      int lazy, int consider_profiling)
142 {
143   struct textrels
144   {
145     caddr_t start;
146     size_t len;
147     int prot;
148     struct textrels *next;
149   } *textrels = NULL;
150   /* Initialize it to make the compiler happy.  */
151   const char *errstring = NULL;
152
153 #ifdef SHARED
154   /* If we are auditing, install the same handlers we need for profiling.  */
155   consider_profiling |= GLRO(dl_audit) != NULL;
156 #elif defined PROF
157   /* Never use dynamic linker profiling for gprof profiling code.  */
158 # define consider_profiling 0
159 #endif
160
161   if (l->l_relocated)
162     return;
163
164   /* If DT_BIND_NOW is set relocate all references in this object.  We
165      do not do this if we are profiling, of course.  */
166   // XXX Correct for auditing?
167   if (!consider_profiling
168       && __builtin_expect (l->l_info[DT_BIND_NOW] != NULL, 0))
169     lazy = 0;
170
171   if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_RELOC, 0))
172     _dl_debug_printf ("\nrelocation processing: %s%s\n",
173                       l->l_name[0] ? l->l_name : rtld_progname,
174                       lazy ? " (lazy)" : "");
175
176   /* DT_TEXTREL is now in level 2 and might phase out at some time.
177      But we rewrite the DT_FLAGS entry to a DT_TEXTREL entry to make
178      testing easier and therefore it will be available at all time.  */
179   if (__builtin_expect (l->l_info[DT_TEXTREL] != NULL, 0))
180     {
181       /* Bletch.  We must make read-only segments writable
182          long enough to relocate them.  */
183       const ElfW(Phdr) *ph;
184       for (ph = l->l_phdr; ph < &l->l_phdr[l->l_phnum]; ++ph)
185         if (ph->p_type == PT_LOAD && (ph->p_flags & PF_W) == 0)
186           {
187             struct textrels *newp;
188
189             newp = (struct textrels *) alloca (sizeof (*newp));
190             newp->len = (((ph->p_vaddr + ph->p_memsz + GLRO(dl_pagesize) - 1)
191                           & ~(GLRO(dl_pagesize) - 1))
192                          - (ph->p_vaddr & ~(GLRO(dl_pagesize) - 1)));
193             newp->start = ((ph->p_vaddr & ~(GLRO(dl_pagesize) - 1))
194                            + (caddr_t) l->l_addr);
195
196             if (__mprotect (newp->start, newp->len, PROT_READ|PROT_WRITE) < 0)
197               {
198                 errstring = N_("cannot make segment writable for relocation");
199               call_error:
200                 _dl_signal_error (errno, l->l_name, NULL, errstring);
201               }
202
203 #if (PF_R | PF_W | PF_X) == 7 && (PROT_READ | PROT_WRITE | PROT_EXEC) == 7
204             newp->prot = (PF_TO_PROT
205                           >> ((ph->p_flags & (PF_R | PF_W | PF_X)) * 4)) & 0xf;
206 #else
207             newp->prot = 0;
208             if (ph->p_flags & PF_R)
209               newp->prot |= PROT_READ;
210             if (ph->p_flags & PF_W)
211               newp->prot |= PROT_WRITE;
212             if (ph->p_flags & PF_X)
213               newp->prot |= PROT_EXEC;
214 #endif
215             newp->next = textrels;
216             textrels = newp;
217           }
218     }
219
220   {
221     /* Do the actual relocation of the object's GOT and other data.  */
222
223     /* String table object symbols.  */
224     const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
225
226     /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code.  */
227 #define RESOLVE_MAP(ref, version, r_type) \
228     (ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL                             \
229      ? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0)                \
230          && elf_machine_type_class (r_type) == l->l_lookup_cache.type_class)  \
231         ? (bump_num_cache_relocations (),                                     \
232            (*ref) = l->l_lookup_cache.ret,                                    \
233            l->l_lookup_cache.value)                                           \
234         : ({ lookup_t _lr;                                                    \
235              int _tc = elf_machine_type_class (r_type);                       \
236              l->l_lookup_cache.type_class = _tc;                              \
237              l->l_lookup_cache.sym = (*ref);                                  \
238              const struct r_found_version *v = NULL;                          \
239              int flags = DL_LOOKUP_ADD_DEPENDENCY;                            \
240              if ((version) != NULL && (version)->hash != 0)                   \
241                {                                                              \
242                  v = (version);                                               \
243                  flags = 0;                                                   \
244                }                                                              \
245              _lr = _dl_lookup_symbol_x (strtab + (*ref)->st_name, l, (ref),   \
246                                         scope, v, _tc, flags, NULL);          \
247              l->l_lookup_cache.ret = (*ref);                                  \
248              l->l_lookup_cache.value = _lr; }))                               \
249      : l)
250
251     /* This macro is used as a callback from elf_machine_rel{a,} when a
252        static TLS reloc is about to be performed.  Since (in dl-load.c) we
253        permit dynamic loading of objects that might use such relocs, we
254        have to check whether each use is actually doable.  If the object
255        whose TLS segment the reference resolves to was allocated space in
256        the static TLS block at startup, then it's ok.  Otherwise, we make
257        an attempt to allocate it in surplus space on the fly.  If that
258        can't be done, we fall back to the error that DF_STATIC_TLS is
259        intended to produce.  */
260 #define CHECK_STATIC_TLS(map, sym_map)                                  \
261     do {                                                                \
262       if (__builtin_expect ((sym_map)->l_tls_offset == NO_TLS_OFFSET    \
263                             || ((sym_map)->l_tls_offset                 \
264                                 == FORCED_DYNAMIC_TLS_OFFSET), 0))      \
265         _dl_allocate_static_tls (sym_map);                              \
266     } while (0)
267
268 #include "dynamic-link.h"
269
270     ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling);
271
272 #ifndef PROF
273     if (__builtin_expect (consider_profiling, 0))
274       {
275         /* Allocate the array which will contain the already found
276            relocations.  If the shared object lacks a PLT (for example
277            if it only contains lead function) the l_info[DT_PLTRELSZ]
278            will be NULL.  */
279         if (l->l_info[DT_PLTRELSZ] == NULL)
280           {
281             errstring = N_("%s: no PLTREL found in object %s\n");
282           fatal:
283             _dl_fatal_printf (errstring,
284                               rtld_progname ?: "<program name unknown>",
285                               l->l_name);
286           }
287
288         l->l_reloc_result = calloc (sizeof (l->l_reloc_result[0]),
289                                     l->l_info[DT_PLTRELSZ]->d_un.d_val);
290         if (l->l_reloc_result == NULL)
291           {
292             errstring = N_("\
293 %s: out of memory to store relocation results for %s\n");
294             goto fatal;
295           }
296       }
297 #endif
298   }
299
300   /* Mark the object so we know this work has been done.  */
301   l->l_relocated = 1;
302
303   /* Undo the segment protection changes.  */
304   while (__builtin_expect (textrels != NULL, 0))
305     {
306       if (__mprotect (textrels->start, textrels->len, textrels->prot) < 0)
307         {
308           errstring = N_("cannot restore segment prot after reloc");
309           goto call_error;
310         }
311
312       textrels = textrels->next;
313     }
314
315   /* In case we can protect the data now that the relocations are
316      done, do it.  */
317   if (l->l_relro_size != 0)
318     _dl_protect_relro (l);
319 }
320
321
322 void internal_function
323 _dl_protect_relro (struct link_map *l)
324 {
325   ElfW(Addr) start = ((l->l_addr + l->l_relro_addr)
326                       & ~(GLRO(dl_pagesize) - 1));
327   ElfW(Addr) end = ((l->l_addr + l->l_relro_addr + l->l_relro_size)
328                     & ~(GLRO(dl_pagesize) - 1));
329
330   if (start != end
331       && __mprotect ((void *) start, end - start, PROT_READ) < 0)
332     {
333       static const char errstring[] = N_("\
334 cannot apply additional memory protection after relocation");
335       _dl_signal_error (errno, l->l_name, NULL, errstring);
336     }
337 }
338
339 void
340 internal_function __attribute_noinline__
341 _dl_reloc_bad_type (struct link_map *map, unsigned int type, int plt)
342 {
343   extern const char INTUSE(_itoa_lower_digits)[] attribute_hidden;
344 #define DIGIT(b)        INTUSE(_itoa_lower_digits)[(b) & 0xf];
345
346   /* XXX We cannot translate these messages.  */
347   static const char msg[2][32
348 #if __ELF_NATIVE_CLASS == 64
349                            + 6
350 #endif
351   ] = { "unexpected reloc type 0x",
352         "unexpected PLT reloc type 0x" };
353   char msgbuf[sizeof (msg[0])];
354   char *cp;
355
356   cp = __stpcpy (msgbuf, msg[plt]);
357 #if __ELF_NATIVE_CLASS == 64
358   if (__builtin_expect(type > 0xff, 0))
359     {
360       *cp++ = DIGIT (type >> 28);
361       *cp++ = DIGIT (type >> 24);
362       *cp++ = DIGIT (type >> 20);
363       *cp++ = DIGIT (type >> 16);
364       *cp++ = DIGIT (type >> 12);
365       *cp++ = DIGIT (type >> 8);
366     }
367 #endif
368   *cp++ = DIGIT (type >> 4);
369   *cp++ = DIGIT (type);
370   *cp = '\0';
371
372   _dl_signal_error (0, map->l_name, NULL, msgbuf);
373 }