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