1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
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 * $FreeBSD$
28 */
29
30/*
31 * Dynamic linker for ELF.
32 *
33 * John Polstra <jdp@polstra.com>.
34 */
35
36#include <sys/param.h>
37#include <sys/mman.h>
38#include <machine/segments.h>
39#include <machine/sysarch.h>
40
41#include <dlfcn.h>
42#include <err.h>
43#include <errno.h>
44#include <fcntl.h>
45#include <stdarg.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <string.h>
49#include <unistd.h>
50
51#include "debug.h"
52#include "rtld.h"
53#include "rtld_tls.h"
54
55/*
56 * Process the special R_386_COPY relocations in the main program.  These
57 * copy data from a shared object into a region in the main program's BSS
58 * segment.
59 *
60 * Returns 0 on success, -1 on failure.
61 */
62int
63do_copy_relocations(Obj_Entry *dstobj)
64{
65    const Elf_Rel *rellim;
66    const Elf_Rel *rel;
67
68    assert(dstobj->mainprog);	/* COPY relocations are invalid elsewhere */
69
70    rellim = (const Elf_Rel *)((const char *)dstobj->rel + dstobj->relsize);
71    for (rel = dstobj->rel;  rel < rellim;  rel++) {
72	if (ELF_R_TYPE(rel->r_info) == R_386_COPY) {
73	    void *dstaddr;
74	    const Elf_Sym *dstsym;
75	    const char *name;
76	    size_t size;
77	    const void *srcaddr;
78	    const Elf_Sym *srcsym;
79	    const Obj_Entry *srcobj, *defobj;
80	    SymLook req;
81	    int res;
82
83	    dstaddr = (void *)(dstobj->relocbase + rel->r_offset);
84	    dstsym = dstobj->symtab + ELF_R_SYM(rel->r_info);
85	    name = dstobj->strtab + dstsym->st_name;
86	    size = dstsym->st_size;
87	    symlook_init(&req, name);
88	    req.ventry = fetch_ventry(dstobj, 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("Undefined symbol \"%s\" referenced from COPY"
103		  " relocation in %s", name, dstobj->path);
104		return -1;
105	    }
106
107	    srcaddr = (const void *)(defobj->relocbase + srcsym->st_value);
108	    memcpy(dstaddr, srcaddr, size);
109	}
110    }
111
112    return 0;
113}
114
115/* Initialize the special GOT entries. */
116void
117init_pltgot(Obj_Entry *obj)
118{
119    if (obj->pltgot != NULL) {
120	obj->pltgot[1] = (Elf_Addr) obj;
121	obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
122    }
123}
124
125/* Process the non-PLT relocations. */
126int
127reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
128    RtldLockState *lockstate)
129{
130	const Elf_Rel *rellim;
131	const Elf_Rel *rel;
132	SymCache *cache;
133	const Elf_Sym *def;
134	const Obj_Entry *defobj;
135	Elf_Addr *where, symval, add;
136	int r;
137
138	r = -1;
139	/*
140	 * The dynamic loader may be called from a thread, we have
141	 * limited amounts of stack available so we cannot use alloca().
142	 */
143	if (obj != obj_rtld) {
144		cache = calloc(obj->dynsymcount, sizeof(SymCache));
145		/* No need to check for NULL here */
146	} else
147		cache = NULL;
148
149	/* Appease some compilers. */
150	symval = 0;
151	def = NULL;
152
153	rellim = (const Elf_Rel *)((const char *)obj->rel + obj->relsize);
154	for (rel = obj->rel;  rel < rellim;  rel++) {
155		switch (ELF_R_TYPE(rel->r_info)) {
156		case R_386_32:
157		case R_386_PC32:
158		case R_386_GLOB_DAT:
159		case R_386_TLS_TPOFF:
160		case R_386_TLS_TPOFF32:
161		case R_386_TLS_DTPMOD32:
162		case R_386_TLS_DTPOFF32:
163			def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
164			    flags, cache, lockstate);
165			if (def == NULL)
166				goto done;
167			if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
168				switch (ELF_R_TYPE(rel->r_info)) {
169				case R_386_32:
170				case R_386_PC32:
171				case R_386_GLOB_DAT:
172					if ((flags & SYMLOOK_IFUNC) == 0) {
173						obj->non_plt_gnu_ifunc = true;
174						continue;
175					}
176					symval = (Elf_Addr)rtld_resolve_ifunc(
177					    defobj, def);
178					break;
179				case R_386_TLS_TPOFF:
180				case R_386_TLS_TPOFF32:
181				case R_386_TLS_DTPMOD32:
182				case R_386_TLS_DTPOFF32:
183					_rtld_error("%s: IFUNC for TLS reloc",
184					    obj->path);
185					goto done;
186				}
187			} else {
188				if ((flags & SYMLOOK_IFUNC) != 0)
189					continue;
190				symval = (Elf_Addr)defobj->relocbase +
191				    def->st_value;
192			}
193			break;
194		default:
195			if ((flags & SYMLOOK_IFUNC) != 0)
196				continue;
197			break;
198		}
199		where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
200
201		switch (ELF_R_TYPE(rel->r_info)) {
202		case R_386_NONE:
203			break;
204		case R_386_32:
205			*where += symval;
206			break;
207		case R_386_PC32:
208		    /*
209		     * I don't think the dynamic linker should ever
210		     * see this type of relocation.  But the
211		     * binutils-2.6 tools sometimes generate it.
212		     */
213		    *where += symval - (Elf_Addr)where;
214		    break;
215		case R_386_COPY:
216			/*
217			 * These are deferred until all other
218			 * relocations have been done.  All we do here
219			 * is make sure that the COPY relocation is
220			 * not in a shared library.  They are allowed
221			 * only in executable files.
222			 */
223			if (!obj->mainprog) {
224				_rtld_error("%s: Unexpected R_386_COPY "
225				    "relocation in shared library", obj->path);
226				goto done;
227			}
228			break;
229		case R_386_GLOB_DAT:
230			*where = symval;
231			break;
232		case R_386_RELATIVE:
233			*where += (Elf_Addr)obj->relocbase;
234			break;
235		case R_386_TLS_TPOFF:
236		case R_386_TLS_TPOFF32:
237			/*
238			 * We lazily allocate offsets for static TLS
239			 * as we see the first relocation that
240			 * references the TLS block. This allows us to
241			 * support (small amounts of) static TLS in
242			 * dynamically loaded modules. If we run out
243			 * of space, we generate an error.
244			 */
245			if (!defobj->tls_done) {
246				if (!allocate_tls_offset(
247				    __DECONST(Obj_Entry *, defobj))) {
248					_rtld_error("%s: No space available "
249					    "for static Thread Local Storage",
250					    obj->path);
251					goto done;
252				}
253			}
254			add = (Elf_Addr)(def->st_value - defobj->tlsoffset);
255			if (ELF_R_TYPE(rel->r_info) == R_386_TLS_TPOFF)
256				*where += add;
257			else
258				*where -= add;
259			break;
260		case R_386_TLS_DTPMOD32:
261			*where += (Elf_Addr)defobj->tlsindex;
262			break;
263		case R_386_TLS_DTPOFF32:
264			*where += (Elf_Addr) def->st_value;
265			break;
266		case R_386_IRELATIVE:
267			obj->irelative_nonplt = true;
268			break;
269		default:
270			_rtld_error("%s: Unsupported relocation type %d"
271			    " in non-PLT relocations\n", obj->path,
272			    ELF_R_TYPE(rel->r_info));
273			goto done;
274		}
275	}
276	r = 0;
277done:
278	free(cache);
279	return (r);
280}
281
282/* Process the PLT relocations. */
283int
284reloc_plt(Obj_Entry *obj, int flags __unused, RtldLockState *lockstate __unused)
285{
286    const Elf_Rel *rellim;
287    const Elf_Rel *rel;
288
289    rellim = (const Elf_Rel *)((const char *)obj->pltrel + obj->pltrelsize);
290    for (rel = obj->pltrel;  rel < rellim;  rel++) {
291	Elf_Addr *where/*, val*/;
292
293	switch (ELF_R_TYPE(rel->r_info)) {
294	case R_386_JMP_SLOT:
295	  /* Relocate the GOT slot pointing into the PLT. */
296	  where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
297	  *where += (Elf_Addr)obj->relocbase;
298	  break;
299
300	case R_386_IRELATIVE:
301	  obj->irelative = true;
302	  break;
303
304	default:
305	  _rtld_error("Unknown relocation type %x in PLT",
306	    ELF_R_TYPE(rel->r_info));
307	  return (-1);
308	}
309    }
310    return 0;
311}
312
313/* Relocate the jump slots in an object. */
314int
315reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
316{
317    const Elf_Rel *rellim;
318    const Elf_Rel *rel;
319
320    if (obj->jmpslots_done)
321	return 0;
322    rellim = (const Elf_Rel *)((const char *)obj->pltrel + obj->pltrelsize);
323    for (rel = obj->pltrel;  rel < rellim;  rel++) {
324	Elf_Addr *where, target;
325	const Elf_Sym *def;
326	const Obj_Entry *defobj;
327
328	switch (ELF_R_TYPE(rel->r_info)) {
329	case R_386_JMP_SLOT:
330	  where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
331	  def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
332		SYMLOOK_IN_PLT | flags, NULL, lockstate);
333	  if (def == NULL)
334	      return (-1);
335	  if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
336	      obj->gnu_ifunc = true;
337	      continue;
338	  }
339	  target = (Elf_Addr)(defobj->relocbase + def->st_value);
340	  reloc_jmpslot(where, target, defobj, obj, rel);
341	  break;
342
343	case R_386_IRELATIVE:
344	  break;
345
346	default:
347	  _rtld_error("Unknown relocation type %x in PLT",
348	    ELF_R_TYPE(rel->r_info));
349	  return (-1);
350	}
351    }
352
353    obj->jmpslots_done = true;
354    return 0;
355}
356
357/* Fixup the jump slot at "where" to transfer control to "target". */
358Elf_Addr
359reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
360    const Obj_Entry *obj __unused, const Obj_Entry *refobj __unused,
361    const Elf_Rel *rel __unused)
362{
363#ifdef dbg
364	dbg("reloc_jmpslot: *%p = %p", where, (void *)target);
365#endif
366	if (!ld_bind_not)
367		*where = target;
368	return (target);
369}
370
371static void
372reloc_iresolve_one(Obj_Entry *obj, const Elf_Rel *rel,
373    RtldLockState *lockstate)
374{
375	Elf_Addr *where, target;
376
377	where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
378	lock_release(rtld_bind_lock, lockstate);
379	target = call_ifunc_resolver(obj->relocbase + *where);
380	wlock_acquire(rtld_bind_lock, lockstate);
381	*where = target;
382}
383
384int
385reloc_iresolve(Obj_Entry *obj, RtldLockState *lockstate)
386{
387	const Elf_Rel *rellim;
388	const Elf_Rel *rel;
389
390	if (!obj->irelative)
391		return (0);
392	obj->irelative = false;
393	rellim = (const Elf_Rel *)((const char *)obj->pltrel + obj->pltrelsize);
394	for (rel = obj->pltrel;  rel < rellim;  rel++) {
395		if (ELF_R_TYPE(rel->r_info) == R_386_IRELATIVE)
396			reloc_iresolve_one(obj, rel, lockstate);
397	}
398	return (0);
399}
400
401int
402reloc_iresolve_nonplt(Obj_Entry *obj, RtldLockState *lockstate)
403{
404	const Elf_Rel *rellim;
405	const Elf_Rel *rel;
406
407	if (!obj->irelative_nonplt)
408		return (0);
409	obj->irelative_nonplt = false;
410	rellim = (const Elf_Rel *)((const char *)obj->rel + obj->relsize);
411	for (rel = obj->rel;  rel < rellim;  rel++) {
412		if (ELF_R_TYPE(rel->r_info) == R_386_IRELATIVE)
413			reloc_iresolve_one(obj, rel, lockstate);
414	}
415	return (0);
416}
417
418int
419reloc_gnu_ifunc(Obj_Entry *obj, int flags, RtldLockState *lockstate)
420{
421    const Elf_Rel *rellim;
422    const Elf_Rel *rel;
423
424    if (!obj->gnu_ifunc)
425	return (0);
426    rellim = (const Elf_Rel *)((const char *)obj->pltrel + obj->pltrelsize);
427    for (rel = obj->pltrel;  rel < rellim;  rel++) {
428	Elf_Addr *where, target;
429	const Elf_Sym *def;
430	const Obj_Entry *defobj;
431
432	switch (ELF_R_TYPE(rel->r_info)) {
433	case R_386_JMP_SLOT:
434	  where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
435	  def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
436		SYMLOOK_IN_PLT | flags, NULL, lockstate);
437	  if (def == NULL)
438	      return (-1);
439	  if (ELF_ST_TYPE(def->st_info) != STT_GNU_IFUNC)
440	      continue;
441	  lock_release(rtld_bind_lock, lockstate);
442	  target = (Elf_Addr)rtld_resolve_ifunc(defobj, def);
443	  wlock_acquire(rtld_bind_lock, lockstate);
444	  reloc_jmpslot(where, target, defobj, obj, rel);
445	  break;
446	}
447    }
448
449    obj->gnu_ifunc = false;
450    return (0);
451}
452
453uint32_t cpu_feature, cpu_feature2, cpu_stdext_feature, cpu_stdext_feature2;
454
455static void
456rtld_cpuid_count(int idx, int cnt, u_int *p)
457{
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
468void
469ifunc_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) : : "eax", "ecx");
490	if (!cpuid_supported)
491		return;
492
493	rtld_cpuid_count(1, 0, p);
494	cpu_feature = p[3];
495	cpu_feature2 = p[2];
496	rtld_cpuid_count(0, 0, p);
497	cpu_high = p[0];
498	if (cpu_high >= 7) {
499		rtld_cpuid_count(7, 0, p);
500		cpu_stdext_feature = p[1];
501		cpu_stdext_feature2 = p[2];
502	}
503}
504
505void
506allocate_initial_tls(Obj_Entry *objs)
507{
508    void* tls;
509
510    /*
511     * Fix the size of the static TLS block by using the maximum
512     * offset allocated so far and adding a bit for dynamic modules to
513     * use.
514     */
515    tls_static_space = tls_last_offset + RTLD_STATIC_TLS_EXTRA;
516    tls = allocate_tls(objs, NULL, 3*sizeof(Elf_Addr), sizeof(Elf_Addr));
517    i386_set_gsbase(tls);
518}
519
520/* GNU ABI */
521__attribute__((__regparm__(1)))
522void *
523___tls_get_addr(tls_index *ti)
524{
525	Elf_Addr **dtvp;
526
527	dtvp = _get_tp();
528	return (tls_get_addr_common(dtvp, ti->ti_module, ti->ti_offset));
529}
530
531/* Sun ABI */
532void *
533__tls_get_addr(tls_index *ti)
534{
535	Elf_Addr **dtvp;
536
537	dtvp = _get_tp();
538	return (tls_get_addr_common(dtvp, ti->ti_module, ti->ti_offset));
539}
540
541size_t
542calculate_first_tls_offset(size_t size, size_t align, size_t offset)
543{
544	size_t res;
545
546	res = roundup(size, align);
547	offset &= align - 1;
548	if (offset != 0)
549		res += align - offset;
550	return (res);
551}
552
553size_t
554calculate_tls_offset(size_t prev_offset, size_t prev_size __unused, size_t size,
555    size_t align, size_t offset)
556{
557	size_t res;
558
559	res = roundup(prev_offset + size, align);
560	offset &= align - 1;
561	if (offset != 0)
562		res += align - offset;
563	return (res);
564}
565size_t
566calculate_tls_end(size_t off, size_t size __unused)
567{
568	return (off);
569}
570