]> git.ipfire.org Git - thirdparty/glibc.git/blame - elf/dl-reloc.c
Update copyright dates 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.
d614a753 2 Copyright (C) 1995-2020 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 16 License along with the GNU C Library; if not, see
5a82c748 17 <https://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>
9090848d 28#include <libc-pointer-arith.h>
d66e34cd
RM
29#include "dynamic-link.h"
30
680254fe 31/* Statistics function. */
d6b5d570
UD
32#ifdef SHARED
33# define bump_num_cache_relocations() ++GL(dl_num_cache_relocations)
be4b5a95 34#else
1b4575ae 35# define bump_num_cache_relocations() ((void) 0)
be4b5a95 36#endif
680254fe 37
3996f34b 38
c56baa87
RM
39/* We are trying to perform a static TLS relocation in MAP, but it was
40 dynamically loaded. This can only work if there is enough surplus in
41 the static TLS area already allocated for each running thread. If this
567678b6 42 object's TLS segment is too big to fit, we fail. If it fits,
9722e6f3
UD
43 we set MAP->l_tls_offset and return.
44 This function intentionally does not return any value but signals error
45 directly, as static TLS should be rare and code handling it should
46 not be inlined as much as possible. */
c9ff0187 47int
c9ff0187 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. */
8a35c3fe
CD
77 size_t offset = (ALIGN_UP(GL(dl_tls_static_used)
78 - map->l_tls_firstbyte_offset,
79 map->l_tls_align)
66bdbaa4
AM
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
17e00cc6 114__attribute_noinline__
c9ff0187
UD
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 138
9722e6f3
UD
139 /* Initialize the memory. */
140 memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
141 '\0', map->l_tls_blocksize - map->l_tls_initimage_size);
c56baa87 142}
c56baa87
RM
143
144
d66e34cd 145void
be935610 146_dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
2ca285b0 147 int reloc_mode, int consider_profiling)
d66e34cd 148{
f133c097
UD
149 struct textrels
150 {
151 caddr_t start;
152 size_t len;
153 int prot;
154 struct textrels *next;
155 } *textrels = NULL;
156 /* Initialize it to make the compiler happy. */
157 const char *errstring = NULL;
2ca285b0 158 int lazy = reloc_mode & RTLD_LAZY;
3a62d00d 159 int skip_ifunc = reloc_mode & __RTLD_NOIFUNC;
f133c097 160
9dcafc55
UD
161#ifdef SHARED
162 /* If we are auditing, install the same handlers we need for profiling. */
2ca285b0
UD
163 if ((reloc_mode & __RTLD_AUDIT) == 0)
164 consider_profiling |= GLRO(dl_audit) != NULL;
9f0d7b6d
UD
165#elif defined PROF
166 /* Never use dynamic linker profiling for gprof profiling code. */
167# define consider_profiling 0
9dcafc55
UD
168#endif
169
d66e34cd
RM
170 if (l->l_relocated)
171 return;
172
88187dcc
UD
173 /* If DT_BIND_NOW is set relocate all references in this object. We
174 do not do this if we are profiling, of course. */
9dcafc55 175 // XXX Correct for auditing?
55e2d5c7
UD
176 if (!consider_profiling
177 && __builtin_expect (l->l_info[DT_BIND_NOW] != NULL, 0))
88187dcc
UD
178 lazy = 0;
179
a1ffb40e 180 if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_RELOC))
154d10bd 181 _dl_debug_printf ("\nrelocation processing: %s%s\n",
b9375348 182 DSO_FILENAME (l->l_name), lazy ? " (lazy)" : "");
8193034b 183
f133c097
UD
184 /* DT_TEXTREL is now in level 2 and might phase out at some time.
185 But we rewrite the DT_FLAGS entry to a DT_TEXTREL entry to make
186 testing easier and therefore it will be available at all time. */
a1ffb40e 187 if (__glibc_unlikely (l->l_info[DT_TEXTREL] != NULL))
d66e34cd
RM
188 {
189 /* Bletch. We must make read-only segments writable
190 long enough to relocate them. */
266180eb 191 const ElfW(Phdr) *ph;
d66e34cd
RM
192 for (ph = l->l_phdr; ph < &l->l_phdr[l->l_phnum]; ++ph)
193 if (ph->p_type == PT_LOAD && (ph->p_flags & PF_W) == 0)
194 {
f133c097
UD
195 struct textrels *newp;
196
197 newp = (struct textrels *) alloca (sizeof (*newp));
8a35c3fe
CD
198 newp->len = ALIGN_UP (ph->p_vaddr + ph->p_memsz, GLRO(dl_pagesize))
199 - ALIGN_DOWN (ph->p_vaddr, GLRO(dl_pagesize));
200 newp->start = PTR_ALIGN_DOWN (ph->p_vaddr, GLRO(dl_pagesize))
201 + (caddr_t) l->l_addr;
f133c097 202
f133c097
UD
203 newp->prot = 0;
204 if (ph->p_flags & PF_R)
205 newp->prot |= PROT_READ;
206 if (ph->p_flags & PF_W)
207 newp->prot |= PROT_WRITE;
208 if (ph->p_flags & PF_X)
209 newp->prot |= PROT_EXEC;
b5c45e83
AZ
210
211 if (__mprotect (newp->start, newp->len, newp->prot|PROT_WRITE) < 0)
212 {
213 errstring = N_("cannot make segment writable for relocation");
214 call_error:
215 _dl_signal_error (errno, l->l_name, NULL, errstring);
216 }
217
f133c097
UD
218 newp->next = textrels;
219 textrels = newp;
d66e34cd
RM
220 }
221 }
222
223 {
ba79d61b 224 /* Do the actual relocation of the object's GOT and other data. */
d66e34cd 225
f420344c 226 /* String table object symbols. */
a42195db 227 const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
d66e34cd 228
f51d1dfd 229 /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */
cf5a372e 230#define RESOLVE_MAP(ref, version, r_type) \
b6084a95
MR
231 ((ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \
232 && __glibc_likely (!dl_symbol_visibility_binds_local_p (*ref))) \
680254fe 233 ? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0) \
cf5a372e 234 && elf_machine_type_class (r_type) == l->l_lookup_cache.type_class) \
1b4575ae 235 ? (bump_num_cache_relocations (), \
680254fe
UD
236 (*ref) = l->l_lookup_cache.ret, \
237 l->l_lookup_cache.value) \
238 : ({ lookup_t _lr; \
cf5a372e
UD
239 int _tc = elf_machine_type_class (r_type); \
240 l->l_lookup_cache.type_class = _tc; \
680254fe 241 l->l_lookup_cache.sym = (*ref); \
021723ab 242 const struct r_found_version *v = NULL; \
021723ab 243 if ((version) != NULL && (version)->hash != 0) \
4fd89462 244 v = (version); \
021723ab 245 _lr = _dl_lookup_symbol_x (strtab + (*ref)->st_name, l, (ref), \
4fd89462 246 scope, v, _tc, \
fcb04b9a
FW
247 DL_LOOKUP_ADD_DEPENDENCY \
248 | DL_LOOKUP_FOR_RELOCATE, NULL); \
680254fe
UD
249 l->l_lookup_cache.ret = (*ref); \
250 l->l_lookup_cache.value = _lr; })) \
c0282c06 251 : l)
f51d1dfd
RM
252
253#include "dynamic-link.h"
647eb037 254
3a62d00d 255 ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc);
ea7eb7e3 256
9f0d7b6d 257#ifndef PROF
3e058c9d
L
258 if (__glibc_unlikely (consider_profiling)
259 && l->l_info[DT_PLTRELSZ] != NULL)
ea7eb7e3
UD
260 {
261 /* Allocate the array which will contain the already found
ea97f90c 262 relocations. If the shared object lacks a PLT (for example
3cfd2d07 263 if it only contains lead function) the l_info[DT_PLTRELSZ]
ea97f90c 264 will be NULL. */
62058ce6
CD
265 size_t sizeofrel = l->l_info[DT_PLTREL]->d_un.d_val == DT_RELA
266 ? sizeof (ElfW(Rela))
267 : sizeof (ElfW(Rel));
268 size_t relcount = l->l_info[DT_PLTRELSZ]->d_un.d_val / sizeofrel;
269 l->l_reloc_result = calloc (sizeof (l->l_reloc_result[0]), relcount);
270
ea7eb7e3 271 if (l->l_reloc_result == NULL)
7982ecfe
UD
272 {
273 errstring = N_("\
9dcafc55 274%s: out of memory to store relocation results for %s\n");
3e058c9d 275 _dl_fatal_printf (errstring, RTLD_PROGNAME, l->l_name);
7982ecfe 276 }
ea7eb7e3 277 }
9f0d7b6d 278#endif
d66e34cd
RM
279 }
280
714a562f 281 /* Mark the object so we know this work has been done. */
d66e34cd
RM
282 l->l_relocated = 1;
283
f133c097
UD
284 /* Undo the segment protection changes. */
285 while (__builtin_expect (textrels != NULL, 0))
d66e34cd 286 {
f133c097
UD
287 if (__mprotect (textrels->start, textrels->len, textrels->prot) < 0)
288 {
289 errstring = N_("cannot restore segment prot after reloc");
290 goto call_error;
291 }
24d60840 292
80da2e09
KS
293#ifdef CLEAR_CACHE
294 CLEAR_CACHE (textrels->start, textrels->start + textrels->len);
295#endif
296
f133c097 297 textrels = textrels->next;
d66e34cd 298 }
ed20b3d9
UD
299
300 /* In case we can protect the data now that the relocations are
301 done, do it. */
302 if (l->l_relro_size != 0)
75631a57
UD
303 _dl_protect_relro (l);
304}
154d10bd 305
ed20b3d9 306
17e00cc6 307void
75631a57
UD
308_dl_protect_relro (struct link_map *l)
309{
8a35c3fe
CD
310 ElfW(Addr) start = ALIGN_DOWN((l->l_addr
311 + l->l_relro_addr),
312 GLRO(dl_pagesize));
313 ElfW(Addr) end = ALIGN_DOWN((l->l_addr
314 + l->l_relro_addr
315 + l->l_relro_size),
316 GLRO(dl_pagesize));
75631a57
UD
317 if (start != end
318 && __mprotect ((void *) start, end - start, PROT_READ) < 0)
319 {
154d10bd 320 static const char errstring[] = N_("\
ed20b3d9 321cannot apply additional memory protection after relocation");
154d10bd 322 _dl_signal_error (errno, l->l_name, NULL, errstring);
ed20b3d9 323 }
d66e34cd 324}
421c80d2
RM
325
326void
17e00cc6 327__attribute_noinline__
ea41b926 328_dl_reloc_bad_type (struct link_map *map, unsigned int type, int plt)
421c80d2 329{
5be8418c 330#define DIGIT(b) _itoa_lower_digits[(b) & 0xf];
ea41b926
UD
331
332 /* XXX We cannot translate these messages. */
58436415
UD
333 static const char msg[2][32
334#if __ELF_NATIVE_CLASS == 64
335 + 6
336#endif
337 ] = { "unexpected reloc type 0x",
338 "unexpected PLT reloc type 0x" };
ea41b926
UD
339 char msgbuf[sizeof (msg[0])];
340 char *cp;
341
342 cp = __stpcpy (msgbuf, msg[plt]);
58436415
UD
343#if __ELF_NATIVE_CLASS == 64
344 if (__builtin_expect(type > 0xff, 0))
345 {
346 *cp++ = DIGIT (type >> 28);
347 *cp++ = DIGIT (type >> 24);
348 *cp++ = DIGIT (type >> 20);
349 *cp++ = DIGIT (type >> 16);
350 *cp++ = DIGIT (type >> 12);
351 *cp++ = DIGIT (type >> 8);
352 }
353#endif
ea41b926 354 *cp++ = DIGIT (type >> 4);
f6fe5826
UD
355 *cp++ = DIGIT (type);
356 *cp = '\0';
ea41b926 357
154d10bd 358 _dl_signal_error (0, map->l_name, NULL, msgbuf);
421c80d2 359}