xref: /freebsd/libexec/rtld-elf/i386/reloc.c (revision dece5b05f577fc4c6b89af7ad48dfbdf7cc4945c)
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 void
55 md_obj_entry_init(Obj_Entry *obj)
56 {
57 	STAILQ_INIT(&obj->tlsdesc_dynargs);
58 }
59 
60 void
61 md_obj_entry_fini(Obj_Entry *obj)
62 {
63 	struct tlsdesc_dynarg *tda, *t;
64 
65 	STAILQ_FOREACH_SAFE(tda, &obj->tlsdesc_dynargs, link, t) {
66 		free(tda);
67 	}
68 }
69 
70 /*
71  * Process the special R_386_COPY relocations in the main program.  These
72  * copy data from a shared object into a region in the main program's BSS
73  * segment.
74  *
75  * Returns 0 on success, -1 on failure.
76  */
77 int
78 do_copy_relocations(Obj_Entry *dstobj)
79 {
80 	const Elf_Rel *rellim;
81 	const Elf_Rel *rel;
82 
83 	assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */
84 
85 	rellim = (const Elf_Rel *)((const char *)dstobj->rel + dstobj->relsize);
86 	for (rel = dstobj->rel; rel < rellim; rel++) {
87 		if (ELF_R_TYPE(rel->r_info) == R_386_COPY) {
88 			void *dstaddr;
89 			const Elf_Sym *dstsym;
90 			const char *name;
91 			size_t size;
92 			const void *srcaddr;
93 			const Elf_Sym *srcsym;
94 			const Obj_Entry *srcobj, *defobj;
95 			SymLook req;
96 			int res;
97 
98 			dstaddr = (void *)(dstobj->relocbase + rel->r_offset);
99 			dstsym = dstobj->symtab + ELF_R_SYM(rel->r_info);
100 			name = dstobj->strtab + dstsym->st_name;
101 			size = dstsym->st_size;
102 			symlook_init(&req, name);
103 			req.ventry = fetch_ventry(dstobj,
104 			    ELF_R_SYM(rel->r_info));
105 			req.flags = SYMLOOK_EARLY;
106 
107 			for (srcobj = globallist_next(dstobj); srcobj != NULL;
108 			    srcobj = globallist_next(srcobj)) {
109 				res = symlook_obj(&req, srcobj);
110 				if (res == 0) {
111 					srcsym = req.sym_out;
112 					defobj = req.defobj_out;
113 					break;
114 				}
115 			}
116 
117 			if (srcobj == NULL) {
118 				_rtld_error(
119 			    "Undefined symbol \"%s\" referenced from COPY"
120 				    " relocation in %s",
121 				    name, dstobj->path);
122 				return (-1);
123 			}
124 
125 			srcaddr = (const void *)(defobj->relocbase +
126 			    srcsym->st_value);
127 			memcpy(dstaddr, srcaddr, size);
128 		}
129 	}
130 
131 	return (0);
132 }
133 
134 /* Initialize the special GOT entries. */
135 void
136 init_pltgot(Obj_Entry *obj)
137 {
138 	if (obj->pltgot != NULL) {
139 		obj->pltgot[1] = (Elf_Addr)obj;
140 		obj->pltgot[2] = (Elf_Addr)&_rtld_bind_start;
141 	}
142 }
143 
144 static struct tlsdesc_dynarg *
145 reloc_tlsdesc_alloc(Obj_Entry *obj, Elf_Addr tlsoffs)
146 {
147 	struct tlsdesc_dynarg *tda;
148 
149 	tda = xmalloc(sizeof(struct tlsdesc_dynarg));
150 	tda->tlsinfo.ti_module = obj->tlsindex;
151 	tda->tlsinfo.ti_offset = tlsoffs;
152 	STAILQ_INSERT_TAIL(&obj->tlsdesc_dynargs, tda, link);
153 	return (tda);
154 }
155 
156 static void
157 reloc_tlsdesc(const Obj_Entry *obj, const Elf_Rel *rel,
158     struct tlsdesc *where, int flags, RtldLockState *lockstate)
159 {
160 	const Elf_Sym *def;
161 	const Obj_Entry *defobj;
162 	Elf_Addr offs;
163 
164 	dbg("reloc_tlsdesc obj %s rel %p where %p", obj->path, rel, where);
165 	offs = 0;
166 	if (ELF_R_SYM(rel->r_info) != 0) {
167 		def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, flags,
168 		    NULL, lockstate);
169 		if (def == NULL)
170 			rtld_die();
171 		if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
172 			_rtld_error("%s: IFUNC for TLSDESC reloc",
173 			    obj->path);
174 			rtld_die();
175 		}
176 		offs = def->st_value;
177 		obj = defobj;
178 		if (def->st_shndx == SHN_UNDEF) {
179 			/* Weak undefined thread variable */
180 			where->entry = rtld_tlsdesc_undef;
181 			return;
182 		}
183 	}
184 	offs += where->offset;
185 
186 	if (obj->tlsoffset != 0) {
187 		/* Variable is in initialy allocated TLS segment */
188 		where->entry = rtld_tlsdesc_static;
189 		where->offset = offs - obj->tlsoffset;
190 	} else {
191 		/* TLS offest is unknown at load time, use dynamic resolving */
192 		where->entry = rtld_tlsdesc_dynamic;
193 		where->arg = reloc_tlsdesc_alloc(__DECONST(Obj_Entry *, obj),
194 		    offs);
195 	}
196 }
197 
198 /* Process the non-PLT relocations. */
199 int
200 reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
201     RtldLockState *lockstate)
202 {
203 	const Elf_Rel *rellim;
204 	const Elf_Rel *rel;
205 	SymCache *cache;
206 	const Elf_Sym *def;
207 	const Obj_Entry *defobj;
208 	Elf_Addr *where, symval, add;
209 	int r;
210 
211 	r = -1;
212 	/*
213 	 * The dynamic loader may be called from a thread, we have
214 	 * limited amounts of stack available so we cannot use alloca().
215 	 */
216 	if (obj != obj_rtld) {
217 		cache = calloc(obj->dynsymcount, sizeof(SymCache));
218 		/* No need to check for NULL here */
219 	} else {
220 		cache = NULL;
221 	}
222 
223 	/* Appease some compilers. */
224 	symval = 0;
225 	def = NULL;
226 
227 	rellim = (const Elf_Rel *)((const char *)obj->rel + obj->relsize);
228 	for (rel = obj->rel; rel < rellim; rel++) {
229 		switch (ELF_R_TYPE(rel->r_info)) {
230 		case R_386_32:
231 		case R_386_PC32:
232 		case R_386_GLOB_DAT:
233 		case R_386_TLS_TPOFF:
234 		case R_386_TLS_TPOFF32:
235 		case R_386_TLS_DTPMOD32:
236 		case R_386_TLS_DTPOFF32:
237 			def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
238 			    flags, cache, lockstate);
239 			if (def == NULL)
240 				goto done;
241 			if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
242 				switch (ELF_R_TYPE(rel->r_info)) {
243 				case R_386_32:
244 				case R_386_PC32:
245 				case R_386_GLOB_DAT:
246 					if ((flags & SYMLOOK_IFUNC) == 0) {
247 						obj->non_plt_gnu_ifunc = true;
248 						continue;
249 					}
250 					symval = (Elf_Addr)
251 					    rtld_resolve_ifunc(defobj, def);
252 					break;
253 				case R_386_TLS_TPOFF:
254 				case R_386_TLS_TPOFF32:
255 				case R_386_TLS_DTPMOD32:
256 				case R_386_TLS_DTPOFF32:
257 					_rtld_error("%s: IFUNC for TLS reloc",
258 					    obj->path);
259 					goto done;
260 				}
261 			} else {
262 				if ((flags & SYMLOOK_IFUNC) != 0)
263 					continue;
264 				symval = (Elf_Addr)defobj->relocbase +
265 				    def->st_value;
266 			}
267 			break;
268 		default:
269 			if ((flags & SYMLOOK_IFUNC) != 0)
270 				continue;
271 			break;
272 		}
273 		where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
274 
275 		switch (ELF_R_TYPE(rel->r_info)) {
276 		case R_386_NONE:
277 			break;
278 		case R_386_32:
279 			*where += symval;
280 			break;
281 		case R_386_PC32:
282 			/*
283 			 * I don't think the dynamic linker should ever
284 			 * see this type of relocation.  But the
285 			 * binutils-2.6 tools sometimes generate it.
286 			 */
287 			*where += symval - (Elf_Addr)where;
288 			break;
289 		case R_386_COPY:
290 			/*
291 			 * These are deferred until all other
292 			 * relocations have been done.  All we do here
293 			 * is make sure that the COPY relocation is
294 			 * not in a shared library.  They are allowed
295 			 * only in executable files.
296 			 */
297 			if (!obj->mainprog) {
298 				_rtld_error(
299 		"%s: Unexpected R_386_COPY relocation in shared library",
300 				    obj->path);
301 				goto done;
302 			}
303 			break;
304 		case R_386_GLOB_DAT:
305 			*where = symval;
306 			break;
307 		case R_386_RELATIVE:
308 			*where += (Elf_Addr)obj->relocbase;
309 			break;
310 		case R_386_TLS_TPOFF:
311 		case R_386_TLS_TPOFF32:
312 			/*
313 			 * We lazily allocate offsets for static TLS
314 			 * as we see the first relocation that
315 			 * references the TLS block. This allows us to
316 			 * support (small amounts of) static TLS in
317 			 * dynamically loaded modules. If we run out
318 			 * of space, we generate an error.
319 			 */
320 			if (!defobj->tls_static) {
321 				if (!allocate_tls_offset(
322 				    __DECONST(Obj_Entry *, defobj))) {
323 					_rtld_error(
324 		"%s: No space available for static Thread Local Storage",
325 					    obj->path);
326 					goto done;
327 				}
328 			}
329 			add = (Elf_Addr)(def->st_value - defobj->tlsoffset);
330 			if (ELF_R_TYPE(rel->r_info) == R_386_TLS_TPOFF)
331 				*where += add;
332 			else
333 				*where -= add;
334 			break;
335 		case R_386_TLS_DTPMOD32:
336 			*where += (Elf_Addr)defobj->tlsindex;
337 			break;
338 		case R_386_TLS_DTPOFF32:
339 			*where += (Elf_Addr)def->st_value;
340 			break;
341 		case R_386_IRELATIVE:
342 			obj->irelative_nonplt = true;
343 			break;
344 		case R_386_TLS_DESC:
345 			reloc_tlsdesc(obj, rel, (struct tlsdesc *)where,
346 			    flags, lockstate);
347 			break;
348 		default:
349 			_rtld_error(
350 		"%s: Unsupported relocation type %d in non-PLT relocations",
351 			    obj->path, ELF_R_TYPE(rel->r_info));
352 			goto done;
353 		}
354 	}
355 	r = 0;
356 done:
357 	free(cache);
358 	return (r);
359 }
360 
361 /* Process the PLT relocations. */
362 int
363 reloc_plt(Obj_Entry *obj, int flags, RtldLockState *lockstate)
364 {
365 	const Elf_Rel *rellim;
366 	const Elf_Rel *rel;
367 
368 	rellim = (const Elf_Rel *)((const char *)obj->pltrel + obj->pltrelsize);
369 	for (rel = obj->pltrel; rel < rellim; rel++) {
370 		Elf_Addr *where;
371 
372 		where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
373 		switch (ELF_R_TYPE(rel->r_info)) {
374 		case R_386_JMP_SLOT:
375 			/* Relocate the GOT slot pointing into the PLT. */
376 			*where += (Elf_Addr)obj->relocbase;
377 			break;
378 
379 		case R_386_IRELATIVE:
380 			obj->irelative = true;
381 			break;
382 
383 		case R_386_TLS_DESC:
384 			reloc_tlsdesc(obj, rel, (struct tlsdesc *)where,
385 			    SYMLOOK_IN_PLT | flags, lockstate);
386 			break;
387 
388 		default:
389 			_rtld_error("Unknown relocation type %x in PLT",
390 			    ELF_R_TYPE(rel->r_info));
391 			return (-1);
392 		}
393 	}
394 	return (0);
395 }
396 
397 /* Relocate the jump slots in an object. */
398 int
399 reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
400 {
401 	const Elf_Rel *rellim;
402 	const Elf_Rel *rel;
403 
404 	if (obj->jmpslots_done)
405 		return (0);
406 	rellim = (const Elf_Rel *)((const char *)obj->pltrel + obj->pltrelsize);
407 	for (rel = obj->pltrel; rel < rellim; rel++) {
408 		Elf_Addr *where, target;
409 		const Elf_Sym *def;
410 		const Obj_Entry *defobj;
411 
412 		switch (ELF_R_TYPE(rel->r_info)) {
413 		case R_386_JMP_SLOT:
414 			where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
415 			def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
416 			    SYMLOOK_IN_PLT | flags, NULL, lockstate);
417 			if (def == NULL)
418 				return (-1);
419 			if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
420 				obj->gnu_ifunc = true;
421 				continue;
422 			}
423 			target = (Elf_Addr)(defobj->relocbase + def->st_value);
424 			reloc_jmpslot(where, target, defobj, obj, rel);
425 			break;
426 
427 		case R_386_IRELATIVE:
428 			break;
429 
430 		default:
431 			_rtld_error("Unknown relocation type %x in PLT",
432 			    ELF_R_TYPE(rel->r_info));
433 			return (-1);
434 		}
435 	}
436 
437 	obj->jmpslots_done = true;
438 	return (0);
439 }
440 
441 /* Fixup the jump slot at "where" to transfer control to "target". */
442 Elf_Addr
443 reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const Obj_Entry *obj __unused,
444     const Obj_Entry *refobj __unused, const Elf_Rel *rel __unused)
445 {
446 	dbg("reloc_jmpslot: *%p = %p", where, (void *)target);
447 	if (!ld_bind_not)
448 		*where = target;
449 	return (target);
450 }
451 
452 static void
453 reloc_iresolve_one(Obj_Entry *obj, const Elf_Rel *rel, RtldLockState *lockstate)
454 {
455 	Elf_Addr *where, target;
456 
457 	where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
458 	lock_release(rtld_bind_lock, lockstate);
459 	target = call_ifunc_resolver(obj->relocbase + *where);
460 	wlock_acquire(rtld_bind_lock, lockstate);
461 	*where = target;
462 }
463 
464 int
465 reloc_iresolve(Obj_Entry *obj, RtldLockState *lockstate)
466 {
467 	const Elf_Rel *rellim;
468 	const Elf_Rel *rel;
469 
470 	if (!obj->irelative)
471 		return (0);
472 	obj->irelative = false;
473 	rellim = (const Elf_Rel *)((const char *)obj->pltrel + obj->pltrelsize);
474 	for (rel = obj->pltrel; rel < rellim; rel++) {
475 		if (ELF_R_TYPE(rel->r_info) == R_386_IRELATIVE)
476 			reloc_iresolve_one(obj, rel, lockstate);
477 	}
478 	return (0);
479 }
480 
481 int
482 reloc_iresolve_nonplt(Obj_Entry *obj, RtldLockState *lockstate)
483 {
484 	const Elf_Rel *rellim;
485 	const Elf_Rel *rel;
486 
487 	if (!obj->irelative_nonplt)
488 		return (0);
489 	obj->irelative_nonplt = false;
490 	rellim = (const Elf_Rel *)((const char *)obj->rel + obj->relsize);
491 	for (rel = obj->rel; rel < rellim; rel++) {
492 		if (ELF_R_TYPE(rel->r_info) == R_386_IRELATIVE)
493 			reloc_iresolve_one(obj, rel, lockstate);
494 	}
495 	return (0);
496 }
497 
498 int
499 reloc_gnu_ifunc(Obj_Entry *obj, int flags, RtldLockState *lockstate)
500 {
501 	const Elf_Rel *rellim;
502 	const Elf_Rel *rel;
503 
504 	if (!obj->gnu_ifunc)
505 		return (0);
506 	rellim = (const Elf_Rel *)((const char *)obj->pltrel + obj->pltrelsize);
507 	for (rel = obj->pltrel; rel < rellim; rel++) {
508 		Elf_Addr *where, target;
509 		const Elf_Sym *def;
510 		const Obj_Entry *defobj;
511 
512 		switch (ELF_R_TYPE(rel->r_info)) {
513 		case R_386_JMP_SLOT:
514 			where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
515 			def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
516 			    SYMLOOK_IN_PLT | flags, NULL, lockstate);
517 			if (def == NULL)
518 				return (-1);
519 			if (ELF_ST_TYPE(def->st_info) != STT_GNU_IFUNC)
520 				continue;
521 			lock_release(rtld_bind_lock, lockstate);
522 			target = (Elf_Addr)rtld_resolve_ifunc(defobj, def);
523 			wlock_acquire(rtld_bind_lock, lockstate);
524 			reloc_jmpslot(where, target, defobj, obj, rel);
525 			break;
526 		}
527 	}
528 
529 	obj->gnu_ifunc = false;
530 	return (0);
531 }
532 
533 uint32_t cpu_feature, cpu_feature2, cpu_stdext_feature, cpu_stdext_feature2;
534 
535 static void
536 rtld_cpuid_count(int idx, int cnt, u_int *p)
537 {
538 	__asm __volatile(
539 	    "	pushl	%%ebx\n"
540 	    "	cpuid\n"
541 	    "	movl	%%ebx,%1\n"
542 	    "	popl	%%ebx\n"
543 	    : "=a"(p[0]), "=r"(p[1]), "=c"(p[2]), "=d"(p[3])
544 	    : "0"(idx), "2"(cnt));
545 }
546 
547 void
548 ifunc_init(Elf_Auxinfo *aux_info[__min_size(AT_COUNT)] __unused)
549 {
550 	u_int p[4], cpu_high;
551 	int cpuid_supported;
552 
553 	__asm __volatile(
554 	    "	pushfl\n"
555 	    "	popl	%%eax\n"
556 	    "	movl    %%eax,%%ecx\n"
557 	    "	xorl    $0x200000,%%eax\n"
558 	    "	pushl	%%eax\n"
559 	    "	popfl\n"
560 	    "	pushfl\n"
561 	    "	popl    %%eax\n"
562 	    "	xorl    %%eax,%%ecx\n"
563 	    "	je	1f\n"
564 	    "	movl	$1,%0\n"
565 	    "	jmp	2f\n"
566 	    "1:	movl	$0,%0\n"
567 	    "2:\n"
568 	    : "=r"(cpuid_supported)
569 	    :
570 	    : "eax", "ecx");
571 	if (!cpuid_supported)
572 		return;
573 
574 	rtld_cpuid_count(1, 0, p);
575 	cpu_feature = p[3];
576 	cpu_feature2 = p[2];
577 	rtld_cpuid_count(0, 0, p);
578 	cpu_high = p[0];
579 	if (cpu_high >= 7) {
580 		rtld_cpuid_count(7, 0, p);
581 		cpu_stdext_feature = p[1];
582 		cpu_stdext_feature2 = p[2];
583 	}
584 }
585 
586 void
587 allocate_initial_tls(Obj_Entry *objs)
588 {
589 	void *tls;
590 
591 	/*
592 	 * Fix the size of the static TLS block by using the maximum
593 	 * offset allocated so far and adding a bit for dynamic modules to
594 	 * use.
595 	 */
596 	tls_static_space = tls_last_offset + ld_static_tls_extra;
597 	tls = allocate_tls(objs, NULL, TLS_TCB_SIZE, TLS_TCB_ALIGN);
598 	_tcb_set(tls);
599 }
600 
601 __GNU_ABI void *
602 ___tls_get_addr(tls_index *ti)
603 {
604 	return (tls_get_addr_common(_tcb_get(), ti->ti_module, ti->ti_offset));
605 }
606 
607 /* Sun ABI */
608 void *
609 __tls_get_addr(tls_index *ti)
610 {
611 	return (tls_get_addr_common(_tcb_get(), ti->ti_module, ti->ti_offset));
612 }
613 
614 size_t
615 calculate_tls_offset(size_t prev_offset, size_t prev_size __unused, size_t size,
616     size_t align, size_t offset)
617 {
618 	size_t res;
619 
620 	/*
621 	 * res is the smallest integer satisfying res - prev_offset >= size
622 	 * and (-res) % p_align = p_vaddr % p_align (= p_offset % p_align).
623 	 */
624 	res = prev_offset + size + align - 1;
625 	res -= (res + offset) & (align - 1);
626 	return (res);
627 }
628 
629 size_t
630 calculate_first_tls_offset(size_t size, size_t align, size_t offset)
631 {
632 	return (calculate_tls_offset(0, 0, size, align, offset));
633 }
634 
635 __GNU_ABI ptrdiff_t
636 rtld_tlsdesc_dynamic_impl(struct tlsdesc *tdp)
637 {
638 	struct tlsdesc_dynarg *tda;
639 	struct tcb *tcb;
640 	tls_index *ti;
641 
642 	tda = tdp->arg;
643 	ti = &tda->tlsinfo;
644 	tcb = _tcb_get();
645 	return ((ptrdiff_t)tls_get_addr_common(tcb, ti->ti_module,
646 	    ti->ti_offset) - (ptrdiff_t)tcb);
647 }
648