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