]> git.ipfire.org Git - thirdparty/glibc.git/blame - elf/dl-reloc.c
Use glibc_likely instead __builtin_expect.
[thirdparty/glibc.git] / elf / dl-reloc.c
CommitLineData
d66e34cd 1/* Relocate a shared object and resolve its references to other loaded objects.
d4697bc9 2 Copyright (C) 1995-2014 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);
73d61e4f
AM
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
73d61e4f 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{
73d61e4f
AM
117 if (map->l_tls_offset == FORCED_DYNAMIC_TLS_OFFSET
118 || _dl_try_allocate_static_tls (map))
c9ff0187
UD
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
a1ffb40e 186 if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_RELOC))
154d10bd 187 _dl_debug_printf ("\nrelocation processing: %s%s\n",
b9375348 188 DSO_FILENAME (l->l_name), lazy ? " (lazy)" : "");
8193034b 189
f133c097
UD
190 /* DT_TEXTREL is now in level 2 and might phase out at some time.
191 But we rewrite the DT_FLAGS entry to a DT_TEXTREL entry to make
192 testing easier and therefore it will be available at all time. */
a1ffb40e 193 if (__glibc_unlikely (l->l_info[DT_TEXTREL] != NULL))
d66e34cd
RM
194 {
195 /* Bletch. We must make read-only segments writable
196 long enough to relocate them. */
266180eb 197 const ElfW(Phdr) *ph;
d66e34cd
RM
198 for (ph = l->l_phdr; ph < &l->l_phdr[l->l_phnum]; ++ph)
199 if (ph->p_type == PT_LOAD && (ph->p_flags & PF_W) == 0)
200 {
f133c097
UD
201 struct textrels *newp;
202
203 newp = (struct textrels *) alloca (sizeof (*newp));
afdca0f2
UD
204 newp->len = (((ph->p_vaddr + ph->p_memsz + GLRO(dl_pagesize) - 1)
205 & ~(GLRO(dl_pagesize) - 1))
206 - (ph->p_vaddr & ~(GLRO(dl_pagesize) - 1)));
207 newp->start = ((ph->p_vaddr & ~(GLRO(dl_pagesize) - 1))
f133c097
UD
208 + (caddr_t) l->l_addr);
209
210 if (__mprotect (newp->start, newp->len, PROT_READ|PROT_WRITE) < 0)
211 {
212 errstring = N_("cannot make segment writable for relocation");
213 call_error:
154d10bd 214 _dl_signal_error (errno, l->l_name, NULL, errstring);
f133c097
UD
215 }
216
217#if (PF_R | PF_W | PF_X) == 7 && (PROT_READ | PROT_WRITE | PROT_EXEC) == 7
218 newp->prot = (PF_TO_PROT
219 >> ((ph->p_flags & (PF_R | PF_W | PF_X)) * 4)) & 0xf;
220#else
221 newp->prot = 0;
222 if (ph->p_flags & PF_R)
223 newp->prot |= PROT_READ;
224 if (ph->p_flags & PF_W)
225 newp->prot |= PROT_WRITE;
226 if (ph->p_flags & PF_X)
227 newp->prot |= PROT_EXEC;
228#endif
229 newp->next = textrels;
230 textrels = newp;
d66e34cd
RM
231 }
232 }
233
234 {
ba79d61b 235 /* Do the actual relocation of the object's GOT and other data. */
d66e34cd 236
f420344c 237 /* String table object symbols. */
a42195db 238 const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
d66e34cd 239
f51d1dfd 240 /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */
cf5a372e 241#define RESOLVE_MAP(ref, version, r_type) \
c0282c06 242 (ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \
680254fe 243 ? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0) \
cf5a372e 244 && elf_machine_type_class (r_type) == l->l_lookup_cache.type_class) \
1b4575ae 245 ? (bump_num_cache_relocations (), \
680254fe
UD
246 (*ref) = l->l_lookup_cache.ret, \
247 l->l_lookup_cache.value) \
248 : ({ lookup_t _lr; \
cf5a372e
UD
249 int _tc = elf_machine_type_class (r_type); \
250 l->l_lookup_cache.type_class = _tc; \
680254fe 251 l->l_lookup_cache.sym = (*ref); \
021723ab 252 const struct r_found_version *v = NULL; \
021723ab 253 if ((version) != NULL && (version)->hash != 0) \
4fd89462 254 v = (version); \
021723ab 255 _lr = _dl_lookup_symbol_x (strtab + (*ref)->st_name, l, (ref), \
4fd89462
UD
256 scope, v, _tc, \
257 DL_LOOKUP_ADD_DEPENDENCY, NULL); \
680254fe
UD
258 l->l_lookup_cache.ret = (*ref); \
259 l->l_lookup_cache.value = _lr; })) \
c0282c06 260 : l)
f51d1dfd
RM
261
262#include "dynamic-link.h"
647eb037 263
3a62d00d 264 ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc);
ea7eb7e3 265
9f0d7b6d 266#ifndef PROF
a1ffb40e 267 if (__glibc_unlikely (consider_profiling))
ea7eb7e3
UD
268 {
269 /* Allocate the array which will contain the already found
ea97f90c 270 relocations. If the shared object lacks a PLT (for example
3cfd2d07 271 if it only contains lead function) the l_info[DT_PLTRELSZ]
ea97f90c
UD
272 will be NULL. */
273 if (l->l_info[DT_PLTRELSZ] == NULL)
7982ecfe 274 {
9dcafc55 275 errstring = N_("%s: no PLTREL found in object %s\n");
7982ecfe
UD
276 fatal:
277 _dl_fatal_printf (errstring,
b9375348 278 RTLD_PROGNAME,
7982ecfe
UD
279 l->l_name);
280 }
ea97f90c 281
9dcafc55
UD
282 l->l_reloc_result = calloc (sizeof (l->l_reloc_result[0]),
283 l->l_info[DT_PLTRELSZ]->d_un.d_val);
ea7eb7e3 284 if (l->l_reloc_result == NULL)
7982ecfe
UD
285 {
286 errstring = N_("\
9dcafc55 287%s: out of memory to store relocation results for %s\n");
7982ecfe
UD
288 goto fatal;
289 }
ea7eb7e3 290 }
9f0d7b6d 291#endif
d66e34cd
RM
292 }
293
714a562f 294 /* Mark the object so we know this work has been done. */
d66e34cd
RM
295 l->l_relocated = 1;
296
f133c097
UD
297 /* Undo the segment protection changes. */
298 while (__builtin_expect (textrels != NULL, 0))
d66e34cd 299 {
f133c097
UD
300 if (__mprotect (textrels->start, textrels->len, textrels->prot) < 0)
301 {
302 errstring = N_("cannot restore segment prot after reloc");
303 goto call_error;
304 }
24d60840 305
80da2e09
KS
306#ifdef CLEAR_CACHE
307 CLEAR_CACHE (textrels->start, textrels->start + textrels->len);
308#endif
309
f133c097 310 textrels = textrels->next;
d66e34cd 311 }
ed20b3d9
UD
312
313 /* In case we can protect the data now that the relocations are
314 done, do it. */
315 if (l->l_relro_size != 0)
75631a57
UD
316 _dl_protect_relro (l);
317}
154d10bd 318
ed20b3d9 319
75631a57
UD
320void internal_function
321_dl_protect_relro (struct link_map *l)
322{
afdca0f2
UD
323 ElfW(Addr) start = ((l->l_addr + l->l_relro_addr)
324 & ~(GLRO(dl_pagesize) - 1));
75631a57 325 ElfW(Addr) end = ((l->l_addr + l->l_relro_addr + l->l_relro_size)
afdca0f2 326 & ~(GLRO(dl_pagesize) - 1));
75631a57
UD
327
328 if (start != end
329 && __mprotect ((void *) start, end - start, PROT_READ) < 0)
330 {
154d10bd 331 static const char errstring[] = N_("\
ed20b3d9 332cannot apply additional memory protection after relocation");
154d10bd 333 _dl_signal_error (errno, l->l_name, NULL, errstring);
ed20b3d9 334 }
d66e34cd 335}
421c80d2
RM
336
337void
567678b6 338internal_function __attribute_noinline__
ea41b926 339_dl_reloc_bad_type (struct link_map *map, unsigned int type, int plt)
421c80d2 340{
5be8418c 341#define DIGIT(b) _itoa_lower_digits[(b) & 0xf];
ea41b926
UD
342
343 /* XXX We cannot translate these messages. */
58436415
UD
344 static const char msg[2][32
345#if __ELF_NATIVE_CLASS == 64
346 + 6
347#endif
348 ] = { "unexpected reloc type 0x",
349 "unexpected PLT reloc type 0x" };
ea41b926
UD
350 char msgbuf[sizeof (msg[0])];
351 char *cp;
352
353 cp = __stpcpy (msgbuf, msg[plt]);
58436415
UD
354#if __ELF_NATIVE_CLASS == 64
355 if (__builtin_expect(type > 0xff, 0))
356 {
357 *cp++ = DIGIT (type >> 28);
358 *cp++ = DIGIT (type >> 24);
359 *cp++ = DIGIT (type >> 20);
360 *cp++ = DIGIT (type >> 16);
361 *cp++ = DIGIT (type >> 12);
362 *cp++ = DIGIT (type >> 8);
363 }
364#endif
ea41b926 365 *cp++ = DIGIT (type >> 4);
f6fe5826
UD
366 *cp++ = DIGIT (type);
367 *cp = '\0';
ea41b926 368
154d10bd 369 _dl_signal_error (0, map->l_name, NULL, msgbuf);
421c80d2 370}