1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright 1996, 1997, 1998, 1999 John D. Polstra.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 /*
29 * Dynamic linker for ELF.
30 *
31 * John Polstra <jdp@polstra.com>.
32 */
33
34 #include <sys/param.h>
35 #include <sys/mman.h>
36
37 #include <machine/segments.h>
38 #include <machine/sysarch.h>
39
40 #include <dlfcn.h>
41 #include <err.h>
42 #include <errno.h>
43 #include <fcntl.h>
44 #include <stdarg.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <unistd.h>
49
50 #include "debug.h"
51 #include "rtld.h"
52 #include "rtld_tls.h"
53
54 /*
55 * Process the special R_386_COPY relocations in the main program. These
56 * copy data from a shared object into a region in the main program's BSS
57 * segment.
58 *
59 * Returns 0 on success, -1 on failure.
60 */
61 int
do_copy_relocations(Obj_Entry * dstobj)62 do_copy_relocations(Obj_Entry *dstobj)
63 {
64 const Elf_Rel *rellim;
65 const Elf_Rel *rel;
66
67 assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */
68
69 rellim = (const Elf_Rel *)((const char *)dstobj->rel + dstobj->relsize);
70 for (rel = dstobj->rel; rel < rellim; rel++) {
71 if (ELF_R_TYPE(rel->r_info) == R_386_COPY) {
72 void *dstaddr;
73 const Elf_Sym *dstsym;
74 const char *name;
75 size_t size;
76 const void *srcaddr;
77 const Elf_Sym *srcsym;
78 const Obj_Entry *srcobj, *defobj;
79 SymLook req;
80 int res;
81
82 dstaddr = (void *)(dstobj->relocbase + rel->r_offset);
83 dstsym = dstobj->symtab + ELF_R_SYM(rel->r_info);
84 name = dstobj->strtab + dstsym->st_name;
85 size = dstsym->st_size;
86 symlook_init(&req, name);
87 req.ventry = fetch_ventry(dstobj,
88 ELF_R_SYM(rel->r_info));
89 req.flags = SYMLOOK_EARLY;
90
91 for (srcobj = globallist_next(dstobj); srcobj != NULL;
92 srcobj = globallist_next(srcobj)) {
93 res = symlook_obj(&req, srcobj);
94 if (res == 0) {
95 srcsym = req.sym_out;
96 defobj = req.defobj_out;
97 break;
98 }
99 }
100
101 if (srcobj == NULL) {
102 _rtld_error(
103 "Undefined symbol \"%s\" referenced from COPY"
104 " relocation in %s",
105 name, dstobj->path);
106 return (-1);
107 }
108
109 srcaddr = (const void *)(defobj->relocbase +
110 srcsym->st_value);
111 memcpy(dstaddr, srcaddr, size);
112 }
113 }
114
115 return (0);
116 }
117
118 /* Initialize the special GOT entries. */
119 void
init_pltgot(Obj_Entry * obj)120 init_pltgot(Obj_Entry *obj)
121 {
122 if (obj->pltgot != NULL) {
123 obj->pltgot[1] = (Elf_Addr)obj;
124 obj->pltgot[2] = (Elf_Addr)&_rtld_bind_start;
125 }
126 }
127
128 /* Process the non-PLT relocations. */
129 int
reloc_non_plt(Obj_Entry * obj,Obj_Entry * obj_rtld,int flags,RtldLockState * lockstate)130 reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
131 RtldLockState *lockstate)
132 {
133 const Elf_Rel *rellim;
134 const Elf_Rel *rel;
135 SymCache *cache;
136 const Elf_Sym *def;
137 const Obj_Entry *defobj;
138 Elf_Addr *where, symval, add;
139 int r;
140
141 r = -1;
142 /*
143 * The dynamic loader may be called from a thread, we have
144 * limited amounts of stack available so we cannot use alloca().
145 */
146 if (obj != obj_rtld) {
147 cache = calloc(obj->dynsymcount, sizeof(SymCache));
148 /* No need to check for NULL here */
149 } else {
150 cache = NULL;
151 }
152
153 /* Appease some compilers. */
154 symval = 0;
155 def = NULL;
156
157 rellim = (const Elf_Rel *)((const char *)obj->rel + obj->relsize);
158 for (rel = obj->rel; rel < rellim; rel++) {
159 switch (ELF_R_TYPE(rel->r_info)) {
160 case R_386_32:
161 case R_386_PC32:
162 case R_386_GLOB_DAT:
163 case R_386_TLS_TPOFF:
164 case R_386_TLS_TPOFF32:
165 case R_386_TLS_DTPMOD32:
166 case R_386_TLS_DTPOFF32:
167 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
168 flags, cache, lockstate);
169 if (def == NULL)
170 goto done;
171 if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
172 switch (ELF_R_TYPE(rel->r_info)) {
173 case R_386_32:
174 case R_386_PC32:
175 case R_386_GLOB_DAT:
176 if ((flags & SYMLOOK_IFUNC) == 0) {
177 obj->non_plt_gnu_ifunc = true;
178 continue;
179 }
180 symval = (Elf_Addr)
181 rtld_resolve_ifunc(defobj, def);
182 break;
183 case R_386_TLS_TPOFF:
184 case R_386_TLS_TPOFF32:
185 case R_386_TLS_DTPMOD32:
186 case R_386_TLS_DTPOFF32:
187 _rtld_error("%s: IFUNC for TLS reloc",
188 obj->path);
189 goto done;
190 }
191 } else {
192 if ((flags & SYMLOOK_IFUNC) != 0)
193 continue;
194 symval = (Elf_Addr)defobj->relocbase +
195 def->st_value;
196 }
197 break;
198 default:
199 if ((flags & SYMLOOK_IFUNC) != 0)
200 continue;
201 break;
202 }
203 where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
204
205 switch (ELF_R_TYPE(rel->r_info)) {
206 case R_386_NONE:
207 break;
208 case R_386_32:
209 *where += symval;
210 break;
211 case R_386_PC32:
212 /*
213 * I don't think the dynamic linker should ever
214 * see this type of relocation. But the
215 * binutils-2.6 tools sometimes generate it.
216 */
217 *where += symval - (Elf_Addr)where;
218 break;
219 case R_386_COPY:
220 /*
221 * These are deferred until all other
222 * relocations have been done. All we do here
223 * is make sure that the COPY relocation is
224 * not in a shared library. They are allowed
225 * only in executable files.
226 */
227 if (!obj->mainprog) {
228 _rtld_error(
229 "%s: Unexpected R_386_COPY relocation in shared library",
230 obj->path);
231 goto done;
232 }
233 break;
234 case R_386_GLOB_DAT:
235 *where = symval;
236 break;
237 case R_386_RELATIVE:
238 *where += (Elf_Addr)obj->relocbase;
239 break;
240 case R_386_TLS_TPOFF:
241 case R_386_TLS_TPOFF32:
242 /*
243 * We lazily allocate offsets for static TLS
244 * as we see the first relocation that
245 * references the TLS block. This allows us to
246 * support (small amounts of) static TLS in
247 * dynamically loaded modules. If we run out
248 * of space, we generate an error.
249 */
250 if (!defobj->tls_static) {
251 if (!allocate_tls_offset(
252 __DECONST(Obj_Entry *, defobj))) {
253 _rtld_error(
254 "%s: No space available for static Thread Local Storage",
255 obj->path);
256 goto done;
257 }
258 }
259 add = (Elf_Addr)(def->st_value - defobj->tlsoffset);
260 if (ELF_R_TYPE(rel->r_info) == R_386_TLS_TPOFF)
261 *where += add;
262 else
263 *where -= add;
264 break;
265 case R_386_TLS_DTPMOD32:
266 *where += (Elf_Addr)defobj->tlsindex;
267 break;
268 case R_386_TLS_DTPOFF32:
269 *where += (Elf_Addr)def->st_value;
270 break;
271 case R_386_IRELATIVE:
272 obj->irelative_nonplt = true;
273 break;
274 default:
275 _rtld_error(
276 "%s: Unsupported relocation type %d in non-PLT relocations",
277 obj->path, ELF_R_TYPE(rel->r_info));
278 goto done;
279 }
280 }
281 r = 0;
282 done:
283 free(cache);
284 return (r);
285 }
286
287 /* Process the PLT relocations. */
288 int
reloc_plt(Obj_Entry * obj,int flags __unused,RtldLockState * lockstate __unused)289 reloc_plt(Obj_Entry *obj, int flags __unused, RtldLockState *lockstate __unused)
290 {
291 const Elf_Rel *rellim;
292 const Elf_Rel *rel;
293
294 rellim = (const Elf_Rel *)((const char *)obj->pltrel + obj->pltrelsize);
295 for (rel = obj->pltrel; rel < rellim; rel++) {
296 Elf_Addr *where;
297
298 switch (ELF_R_TYPE(rel->r_info)) {
299 case R_386_JMP_SLOT:
300 /* Relocate the GOT slot pointing into the PLT. */
301 where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
302 *where += (Elf_Addr)obj->relocbase;
303 break;
304
305 case R_386_IRELATIVE:
306 obj->irelative = true;
307 break;
308
309 default:
310 _rtld_error("Unknown relocation type %x in PLT",
311 ELF_R_TYPE(rel->r_info));
312 return (-1);
313 }
314 }
315 return (0);
316 }
317
318 /* Relocate the jump slots in an object. */
319 int
reloc_jmpslots(Obj_Entry * obj,int flags,RtldLockState * lockstate)320 reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
321 {
322 const Elf_Rel *rellim;
323 const Elf_Rel *rel;
324
325 if (obj->jmpslots_done)
326 return (0);
327 rellim = (const Elf_Rel *)((const char *)obj->pltrel + obj->pltrelsize);
328 for (rel = obj->pltrel; rel < rellim; rel++) {
329 Elf_Addr *where, target;
330 const Elf_Sym *def;
331 const Obj_Entry *defobj;
332
333 switch (ELF_R_TYPE(rel->r_info)) {
334 case R_386_JMP_SLOT:
335 where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
336 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
337 SYMLOOK_IN_PLT | flags, NULL, lockstate);
338 if (def == NULL)
339 return (-1);
340 if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
341 obj->gnu_ifunc = true;
342 continue;
343 }
344 target = (Elf_Addr)(defobj->relocbase + def->st_value);
345 reloc_jmpslot(where, target, defobj, obj, rel);
346 break;
347
348 case R_386_IRELATIVE:
349 break;
350
351 default:
352 _rtld_error("Unknown relocation type %x in PLT",
353 ELF_R_TYPE(rel->r_info));
354 return (-1);
355 }
356 }
357
358 obj->jmpslots_done = true;
359 return (0);
360 }
361
362 /* Fixup the jump slot at "where" to transfer control to "target". */
363 Elf_Addr
reloc_jmpslot(Elf_Addr * where,Elf_Addr target,const Obj_Entry * obj __unused,const Obj_Entry * refobj __unused,const Elf_Rel * rel __unused)364 reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const Obj_Entry *obj __unused,
365 const Obj_Entry *refobj __unused, const Elf_Rel *rel __unused)
366 {
367 dbg("reloc_jmpslot: *%p = %p", where, (void *)target);
368 if (!ld_bind_not)
369 *where = target;
370 return (target);
371 }
372
373 static void
reloc_iresolve_one(Obj_Entry * obj,const Elf_Rel * rel,RtldLockState * lockstate)374 reloc_iresolve_one(Obj_Entry *obj, const Elf_Rel *rel, RtldLockState *lockstate)
375 {
376 Elf_Addr *where, target;
377
378 where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
379 lock_release(rtld_bind_lock, lockstate);
380 target = call_ifunc_resolver(obj->relocbase + *where);
381 wlock_acquire(rtld_bind_lock, lockstate);
382 *where = target;
383 }
384
385 int
reloc_iresolve(Obj_Entry * obj,RtldLockState * lockstate)386 reloc_iresolve(Obj_Entry *obj, RtldLockState *lockstate)
387 {
388 const Elf_Rel *rellim;
389 const Elf_Rel *rel;
390
391 if (!obj->irelative)
392 return (0);
393 obj->irelative = false;
394 rellim = (const Elf_Rel *)((const char *)obj->pltrel + obj->pltrelsize);
395 for (rel = obj->pltrel; rel < rellim; rel++) {
396 if (ELF_R_TYPE(rel->r_info) == R_386_IRELATIVE)
397 reloc_iresolve_one(obj, rel, lockstate);
398 }
399 return (0);
400 }
401
402 int
reloc_iresolve_nonplt(Obj_Entry * obj,RtldLockState * lockstate)403 reloc_iresolve_nonplt(Obj_Entry *obj, RtldLockState *lockstate)
404 {
405 const Elf_Rel *rellim;
406 const Elf_Rel *rel;
407
408 if (!obj->irelative_nonplt)
409 return (0);
410 obj->irelative_nonplt = false;
411 rellim = (const Elf_Rel *)((const char *)obj->rel + obj->relsize);
412 for (rel = obj->rel; rel < rellim; rel++) {
413 if (ELF_R_TYPE(rel->r_info) == R_386_IRELATIVE)
414 reloc_iresolve_one(obj, rel, lockstate);
415 }
416 return (0);
417 }
418
419 int
reloc_gnu_ifunc(Obj_Entry * obj,int flags,RtldLockState * lockstate)420 reloc_gnu_ifunc(Obj_Entry *obj, int flags, RtldLockState *lockstate)
421 {
422 const Elf_Rel *rellim;
423 const Elf_Rel *rel;
424
425 if (!obj->gnu_ifunc)
426 return (0);
427 rellim = (const Elf_Rel *)((const char *)obj->pltrel + obj->pltrelsize);
428 for (rel = obj->pltrel; rel < rellim; rel++) {
429 Elf_Addr *where, target;
430 const Elf_Sym *def;
431 const Obj_Entry *defobj;
432
433 switch (ELF_R_TYPE(rel->r_info)) {
434 case R_386_JMP_SLOT:
435 where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
436 def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
437 SYMLOOK_IN_PLT | flags, NULL, lockstate);
438 if (def == NULL)
439 return (-1);
440 if (ELF_ST_TYPE(def->st_info) != STT_GNU_IFUNC)
441 continue;
442 lock_release(rtld_bind_lock, lockstate);
443 target = (Elf_Addr)rtld_resolve_ifunc(defobj, def);
444 wlock_acquire(rtld_bind_lock, lockstate);
445 reloc_jmpslot(where, target, defobj, obj, rel);
446 break;
447 }
448 }
449
450 obj->gnu_ifunc = false;
451 return (0);
452 }
453
454 uint32_t cpu_feature, cpu_feature2, cpu_stdext_feature, cpu_stdext_feature2;
455
456 static void
rtld_cpuid_count(int idx,int cnt,u_int * p)457 rtld_cpuid_count(int idx, int cnt, u_int *p)
458 {
459 __asm __volatile(
460 " pushl %%ebx\n"
461 " cpuid\n"
462 " movl %%ebx,%1\n"
463 " popl %%ebx\n"
464 : "=a"(p[0]), "=r"(p[1]), "=c"(p[2]), "=d"(p[3])
465 : "0"(idx), "2"(cnt));
466 }
467
468 void
ifunc_init(Elf_Auxinfo * aux_info[__min_size (AT_COUNT)]__unused)469 ifunc_init(Elf_Auxinfo *aux_info[__min_size(AT_COUNT)] __unused)
470 {
471 u_int p[4], cpu_high;
472 int cpuid_supported;
473
474 __asm __volatile(
475 " pushfl\n"
476 " popl %%eax\n"
477 " movl %%eax,%%ecx\n"
478 " xorl $0x200000,%%eax\n"
479 " pushl %%eax\n"
480 " popfl\n"
481 " pushfl\n"
482 " popl %%eax\n"
483 " xorl %%eax,%%ecx\n"
484 " je 1f\n"
485 " movl $1,%0\n"
486 " jmp 2f\n"
487 "1: movl $0,%0\n"
488 "2:\n"
489 : "=r"(cpuid_supported)
490 :
491 : "eax", "ecx");
492 if (!cpuid_supported)
493 return;
494
495 rtld_cpuid_count(1, 0, p);
496 cpu_feature = p[3];
497 cpu_feature2 = p[2];
498 rtld_cpuid_count(0, 0, p);
499 cpu_high = p[0];
500 if (cpu_high >= 7) {
501 rtld_cpuid_count(7, 0, p);
502 cpu_stdext_feature = p[1];
503 cpu_stdext_feature2 = p[2];
504 }
505 }
506
507 void
allocate_initial_tls(Obj_Entry * objs)508 allocate_initial_tls(Obj_Entry *objs)
509 {
510 void *tls;
511
512 /*
513 * Fix the size of the static TLS block by using the maximum
514 * offset allocated so far and adding a bit for dynamic modules to
515 * use.
516 */
517 tls_static_space = tls_last_offset + ld_static_tls_extra;
518 tls = allocate_tls(objs, NULL, TLS_TCB_SIZE, TLS_TCB_ALIGN);
519 _tcb_set(tls);
520 }
521
522 /* GNU ABI */
523 __attribute__((__regparm__(1))) void *
___tls_get_addr(tls_index * ti)524 ___tls_get_addr(tls_index *ti)
525 {
526 uintptr_t **dtvp;
527
528 dtvp = &_tcb_get()->tcb_dtv;
529 return (tls_get_addr_common(dtvp, ti->ti_module, ti->ti_offset));
530 }
531
532 /* Sun ABI */
533 void *
__tls_get_addr(tls_index * ti)534 __tls_get_addr(tls_index *ti)
535 {
536 uintptr_t **dtvp;
537
538 dtvp = &_tcb_get()->tcb_dtv;
539 return (tls_get_addr_common(dtvp, ti->ti_module, ti->ti_offset));
540 }
541
542 size_t
calculate_tls_offset(size_t prev_offset,size_t prev_size __unused,size_t size,size_t align,size_t offset)543 calculate_tls_offset(size_t prev_offset, size_t prev_size __unused, size_t size,
544 size_t align, size_t offset)
545 {
546 size_t res;
547
548 /*
549 * res is the smallest integer satisfying res - prev_offset >= size
550 * and (-res) % p_align = p_vaddr % p_align (= p_offset % p_align).
551 */
552 res = prev_offset + size + align - 1;
553 res -= (res + offset) & (align - 1);
554 return (res);
555 }
556
557 size_t
calculate_first_tls_offset(size_t size,size_t align,size_t offset)558 calculate_first_tls_offset(size_t size, size_t align, size_t offset)
559 {
560 return (calculate_tls_offset(0, 0, size, align, offset));
561 }
562