]> git.ipfire.org Git - thirdparty/glibc.git/blame - elf/dl-reloc.c
Update copyright notices with scripts/update-copyrights.
[thirdparty/glibc.git] / elf / dl-reloc.c
CommitLineData
d66e34cd 1/* Relocate a shared object and resolve its references to other loaded objects.
568035b7 2 Copyright (C) 1995-2013 Free Software Foundation, Inc.
afd4eb37 3 This file is part of the GNU C Library.
d66e34cd 4
afd4eb37 5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
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.
d66e34cd 9
afd4eb37
UD
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
41bdb6e2 13 Lesser General Public License for more details.
d66e34cd 14
41bdb6e2 15 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
d66e34cd 18
ea7eb7e3 19#include <errno.h>
8e17ea58 20#include <libintl.h>
ea7eb7e3 21#include <stdlib.h>
d66e34cd 22#include <unistd.h>
a42195db 23#include <ldsodefs.h>
ea7eb7e3 24#include <sys/mman.h>
af8bf6bd 25#include <sys/param.h>
ea7eb7e3 26#include <sys/types.h>
5be8418c 27#include <_itoa.h>
d66e34cd
RM
28#include "dynamic-link.h"
29
680254fe 30/* Statistics function. */
d6b5d570
UD
31#ifdef SHARED
32# define bump_num_cache_relocations() ++GL(dl_num_cache_relocations)
be4b5a95 33#else
1b4575ae 34# define bump_num_cache_relocations() ((void) 0)
be4b5a95 35#endif
680254fe 36
3996f34b 37
c56baa87
RM
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
567678b6 41 object's TLS segment is too big to fit, we fail. If it fits,
9722e6f3
UD
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. */
c9ff0187
UD
46int
47internal_function
48_dl_try_allocate_static_tls (struct link_map *map)
c56baa87 49{
4c533566
UD
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))
9722e6f3
UD
54 {
55 fail:
c9ff0187 56 return -1;
9722e6f3 57 }
7ed33cba 58
11bf311e 59#if TLS_TCB_AT_TP
66bdbaa4 60 size_t freebytes = GL(dl_tls_static_size) - GL(dl_tls_static_used);
96553893
UD
61 if (freebytes < TLS_TCB_SIZE)
62 goto fail;
63 freebytes -= TLS_TCB_SIZE;
99fe3b0e 64
66bdbaa4 65 size_t blsize = map->l_tls_blocksize + map->l_tls_firstbyte_offset;
99fe3b0e 66 if (freebytes < blsize)
9722e6f3 67 goto fail;
99fe3b0e 68
66bdbaa4 69 size_t n = (freebytes - blsize) / map->l_tls_align;
99fe3b0e 70
9dcafc55
UD
71 size_t offset = GL(dl_tls_static_used) + (freebytes - n * map->l_tls_align
72 - map->l_tls_firstbyte_offset);
99fe3b0e
UD
73
74 map->l_tls_offset = GL(dl_tls_static_used) = offset;
11bf311e 75#elif TLS_DTV_AT_TP
c56baa87 76 /* dl_tls_static_used includes the TCB at the beginning. */
66bdbaa4
AM
77 size_t offset = (((GL(dl_tls_static_used)
78 - map->l_tls_firstbyte_offset
79 + map->l_tls_align - 1) & -map->l_tls_align)
80 + map->l_tls_firstbyte_offset);
81 size_t used = offset + map->l_tls_blocksize;
7ed33cba 82
66bdbaa4 83 if (used > GL(dl_tls_static_size))
9722e6f3 84 goto fail;
7ed33cba 85
c56baa87 86 map->l_tls_offset = offset;
66bdbaa4 87 map->l_tls_firstbyte_offset = GL(dl_tls_static_used);
7ed33cba 88 GL(dl_tls_static_used) = used;
11bf311e
UD
89#else
90# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
91#endif
99fe3b0e 92
9dcafc55
UD
93 /* If the object is not yet relocated we cannot initialize the
94 static TLS region. Delay it. */
95 if (map->l_real->l_relocated)
96 {
97#ifdef SHARED
98 if (__builtin_expect (THREAD_DTV()[0].counter != GL(dl_tls_generation),
99 0))
100 /* Update the slot information data for at least the generation of
101 the DSO we are allocating data for. */
102 (void) _dl_update_slotinfo (map->l_tls_modid);
103#endif
104
105 GL(dl_init_static_tls) (map);
106 }
9722e6f3
UD
107 else
108 map->l_need_tls_init = 1;
c9ff0187
UD
109
110 return 0;
111}
112
113void
114internal_function __attribute_noinline__
115_dl_allocate_static_tls (struct link_map *map)
116{
117 if (map->l_tls_offset == FORCED_DYNAMIC_TLS_OFFSET
118 || _dl_try_allocate_static_tls (map))
119 {
120 _dl_signal_error (0, map->l_name, NULL, N_("\
121cannot allocate memory in static TLS block"));
122 }
9722e6f3
UD
123}
124
125/* Initialize static TLS area and DTV for current (only) thread.
126 libpthread implementations should provide their own hook
127 to handle all threads. */
128void
129_dl_nothread_init_static_tls (struct link_map *map)
130{
11bf311e 131#if TLS_TCB_AT_TP
9722e6f3 132 void *dest = (char *) THREAD_SELF - map->l_tls_offset;
11bf311e 133#elif TLS_DTV_AT_TP
9722e6f3 134 void *dest = (char *) THREAD_SELF + map->l_tls_offset + TLS_PRE_TCB_SIZE;
11bf311e
UD
135#else
136# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
137#endif
9722e6f3
UD
138
139 /* Fill in the DTV slot so that a later LD/GD access will find it. */
af272d4f 140 dtv_t *dtv = THREAD_DTV ();
e13e33e2 141 assert (map->l_tls_modid <= dtv[-1].counter);
af272d4f
UD
142 dtv[map->l_tls_modid].pointer.val = dest;
143 dtv[map->l_tls_modid].pointer.is_static = true;
9722e6f3
UD
144
145 /* Initialize the memory. */
146 memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
147 '\0', map->l_tls_blocksize - map->l_tls_initimage_size);
c56baa87 148}
c56baa87
RM
149
150
d66e34cd 151void
be935610 152_dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
2ca285b0 153 int reloc_mode, int consider_profiling)
d66e34cd 154{
f133c097
UD
155 struct textrels
156 {
157 caddr_t start;
158 size_t len;
159 int prot;
160 struct textrels *next;
161 } *textrels = NULL;
162 /* Initialize it to make the compiler happy. */
163 const char *errstring = NULL;
2ca285b0 164 int lazy = reloc_mode & RTLD_LAZY;
3a62d00d 165 int skip_ifunc = reloc_mode & __RTLD_NOIFUNC;
f133c097 166
9dcafc55
UD
167#ifdef SHARED
168 /* If we are auditing, install the same handlers we need for profiling. */
2ca285b0
UD
169 if ((reloc_mode & __RTLD_AUDIT) == 0)
170 consider_profiling |= GLRO(dl_audit) != NULL;
9f0d7b6d
UD
171#elif defined PROF
172 /* Never use dynamic linker profiling for gprof profiling code. */
173# define consider_profiling 0
9dcafc55
UD
174#endif
175
d66e34cd
RM
176 if (l->l_relocated)
177 return;
178
88187dcc
UD
179 /* If DT_BIND_NOW is set relocate all references in this object. We
180 do not do this if we are profiling, of course. */
9dcafc55 181 // XXX Correct for auditing?
55e2d5c7
UD
182 if (!consider_profiling
183 && __builtin_expect (l->l_info[DT_BIND_NOW] != NULL, 0))
88187dcc
UD
184 lazy = 0;
185
afdca0f2 186 if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_RELOC, 0))
154d10bd
UD
187 _dl_debug_printf ("\nrelocation processing: %s%s\n",
188 l->l_name[0] ? l->l_name : rtld_progname,
189 lazy ? " (lazy)" : "");
8193034b 190
f133c097
UD
191 /* DT_TEXTREL is now in level 2 and might phase out at some time.
192 But we rewrite the DT_FLAGS entry to a DT_TEXTREL entry to make
193 testing easier and therefore it will be available at all time. */
dc051821 194 if (__builtin_expect (l->l_info[DT_TEXTREL] != NULL, 0))
d66e34cd
RM
195 {
196 /* Bletch. We must make read-only segments writable
197 long enough to relocate them. */
266180eb 198 const ElfW(Phdr) *ph;
d66e34cd
RM
199 for (ph = l->l_phdr; ph < &l->l_phdr[l->l_phnum]; ++ph)
200 if (ph->p_type == PT_LOAD && (ph->p_flags & PF_W) == 0)
201 {
f133c097
UD
202 struct textrels *newp;
203
204 newp = (struct textrels *) alloca (sizeof (*newp));
afdca0f2
UD
205 newp->len = (((ph->p_vaddr + ph->p_memsz + GLRO(dl_pagesize) - 1)
206 & ~(GLRO(dl_pagesize) - 1))
207 - (ph->p_vaddr & ~(GLRO(dl_pagesize) - 1)));
208 newp->start = ((ph->p_vaddr & ~(GLRO(dl_pagesize) - 1))
f133c097
UD
209 + (caddr_t) l->l_addr);
210
211 if (__mprotect (newp->start, newp->len, PROT_READ|PROT_WRITE) < 0)
212 {
213 errstring = N_("cannot make segment writable for relocation");
214 call_error:
154d10bd 215 _dl_signal_error (errno, l->l_name, NULL, errstring);
f133c097
UD
216 }
217
218#if (PF_R | PF_W | PF_X) == 7 && (PROT_READ | PROT_WRITE | PROT_EXEC) == 7
219 newp->prot = (PF_TO_PROT
220 >> ((ph->p_flags & (PF_R | PF_W | PF_X)) * 4)) & 0xf;
221#else
222 newp->prot = 0;
223 if (ph->p_flags & PF_R)
224 newp->prot |= PROT_READ;
225 if (ph->p_flags & PF_W)
226 newp->prot |= PROT_WRITE;
227 if (ph->p_flags & PF_X)
228 newp->prot |= PROT_EXEC;
229#endif
230 newp->next = textrels;
231 textrels = newp;
d66e34cd
RM
232 }
233 }
234
235 {
ba79d61b 236 /* Do the actual relocation of the object's GOT and other data. */
d66e34cd 237
f420344c 238 /* String table object symbols. */
a42195db 239 const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
d66e34cd 240
f51d1dfd 241 /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */
cf5a372e 242#define RESOLVE_MAP(ref, version, r_type) \
c0282c06 243 (ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \
680254fe 244 ? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0) \
cf5a372e 245 && elf_machine_type_class (r_type) == l->l_lookup_cache.type_class) \
1b4575ae 246 ? (bump_num_cache_relocations (), \
680254fe
UD
247 (*ref) = l->l_lookup_cache.ret, \
248 l->l_lookup_cache.value) \
249 : ({ lookup_t _lr; \
cf5a372e
UD
250 int _tc = elf_machine_type_class (r_type); \
251 l->l_lookup_cache.type_class = _tc; \
680254fe 252 l->l_lookup_cache.sym = (*ref); \
021723ab 253 const struct r_found_version *v = NULL; \
021723ab 254 if ((version) != NULL && (version)->hash != 0) \
4fd89462 255 v = (version); \
021723ab 256 _lr = _dl_lookup_symbol_x (strtab + (*ref)->st_name, l, (ref), \
4fd89462
UD
257 scope, v, _tc, \
258 DL_LOOKUP_ADD_DEPENDENCY, NULL); \
680254fe
UD
259 l->l_lookup_cache.ret = (*ref); \
260 l->l_lookup_cache.value = _lr; })) \
c0282c06 261 : l)
f51d1dfd
RM
262
263#include "dynamic-link.h"
647eb037 264
3a62d00d 265 ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc);
ea7eb7e3 266
9f0d7b6d 267#ifndef PROF
67c94753 268 if (__builtin_expect (consider_profiling, 0))
ea7eb7e3
UD
269 {
270 /* Allocate the array which will contain the already found
ea97f90c 271 relocations. If the shared object lacks a PLT (for example
3cfd2d07 272 if it only contains lead function) the l_info[DT_PLTRELSZ]
ea97f90c
UD
273 will be NULL. */
274 if (l->l_info[DT_PLTRELSZ] == NULL)
7982ecfe 275 {
9dcafc55 276 errstring = N_("%s: no PLTREL found in object %s\n");
7982ecfe
UD
277 fatal:
278 _dl_fatal_printf (errstring,
e6caf4e1 279 rtld_progname ?: "<program name unknown>",
7982ecfe
UD
280 l->l_name);
281 }
ea97f90c 282
9dcafc55
UD
283 l->l_reloc_result = calloc (sizeof (l->l_reloc_result[0]),
284 l->l_info[DT_PLTRELSZ]->d_un.d_val);
ea7eb7e3 285 if (l->l_reloc_result == NULL)
7982ecfe
UD
286 {
287 errstring = N_("\
9dcafc55 288%s: out of memory to store relocation results for %s\n");
7982ecfe
UD
289 goto fatal;
290 }
ea7eb7e3 291 }
9f0d7b6d 292#endif
d66e34cd
RM
293 }
294
714a562f 295 /* Mark the object so we know this work has been done. */
d66e34cd
RM
296 l->l_relocated = 1;
297
f133c097
UD
298 /* Undo the segment protection changes. */
299 while (__builtin_expect (textrels != NULL, 0))
d66e34cd 300 {
f133c097
UD
301 if (__mprotect (textrels->start, textrels->len, textrels->prot) < 0)
302 {
303 errstring = N_("cannot restore segment prot after reloc");
304 goto call_error;
305 }
24d60840 306
80da2e09
KS
307#ifdef CLEAR_CACHE
308 CLEAR_CACHE (textrels->start, textrels->start + textrels->len);
309#endif
310
f133c097 311 textrels = textrels->next;
d66e34cd 312 }
ed20b3d9
UD
313
314 /* In case we can protect the data now that the relocations are
315 done, do it. */
316 if (l->l_relro_size != 0)
75631a57
UD
317 _dl_protect_relro (l);
318}
154d10bd 319
ed20b3d9 320
75631a57
UD
321void internal_function
322_dl_protect_relro (struct link_map *l)
323{
afdca0f2
UD
324 ElfW(Addr) start = ((l->l_addr + l->l_relro_addr)
325 & ~(GLRO(dl_pagesize) - 1));
75631a57 326 ElfW(Addr) end = ((l->l_addr + l->l_relro_addr + l->l_relro_size)
afdca0f2 327 & ~(GLRO(dl_pagesize) - 1));
75631a57
UD
328
329 if (start != end
330 && __mprotect ((void *) start, end - start, PROT_READ) < 0)
331 {
154d10bd 332 static const char errstring[] = N_("\
ed20b3d9 333cannot apply additional memory protection after relocation");
154d10bd 334 _dl_signal_error (errno, l->l_name, NULL, errstring);
ed20b3d9 335 }
d66e34cd 336}
421c80d2
RM
337
338void
567678b6 339internal_function __attribute_noinline__
ea41b926 340_dl_reloc_bad_type (struct link_map *map, unsigned int type, int plt)
421c80d2 341{
5be8418c 342#define DIGIT(b) _itoa_lower_digits[(b) & 0xf];
ea41b926
UD
343
344 /* XXX We cannot translate these messages. */
58436415
UD
345 static const char msg[2][32
346#if __ELF_NATIVE_CLASS == 64
347 + 6
348#endif
349 ] = { "unexpected reloc type 0x",
350 "unexpected PLT reloc type 0x" };
ea41b926
UD
351 char msgbuf[sizeof (msg[0])];
352 char *cp;
353
354 cp = __stpcpy (msgbuf, msg[plt]);
58436415
UD
355#if __ELF_NATIVE_CLASS == 64
356 if (__builtin_expect(type > 0xff, 0))
357 {
358 *cp++ = DIGIT (type >> 28);
359 *cp++ = DIGIT (type >> 24);
360 *cp++ = DIGIT (type >> 20);
361 *cp++ = DIGIT (type >> 16);
362 *cp++ = DIGIT (type >> 12);
363 *cp++ = DIGIT (type >> 8);
364 }
365#endif
ea41b926 366 *cp++ = DIGIT (type >> 4);
f6fe5826
UD
367 *cp++ = DIGIT (type);
368 *cp = '\0';
ea41b926 369
154d10bd 370 _dl_signal_error (0, map->l_name, NULL, msgbuf);
421c80d2 371}