reloc.c revision 271469
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/amd64/reloc.c 271469 2014-09-12 16:22:01Z 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/sysarch.h>
37
38#include <dlfcn.h>
39#include <err.h>
40#include <errno.h>
41#include <fcntl.h>
42#include <stdarg.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <string.h>
46#include <unistd.h>
47
48#include "debug.h"
49#include "rtld.h"
50
51/*
52 * Process the special R_X86_64_COPY relocations in the main program.  These
53 * copy data from a shared object into a region in the main program's BSS
54 * segment.
55 *
56 * Returns 0 on success, -1 on failure.
57 */
58int
59do_copy_relocations(Obj_Entry *dstobj)
60{
61    const Elf_Rela *relalim;
62    const Elf_Rela *rela;
63
64    assert(dstobj->mainprog);	/* COPY relocations are invalid elsewhere */
65
66    relalim = (const Elf_Rela *) ((caddr_t) dstobj->rela + dstobj->relasize);
67    for (rela = dstobj->rela;  rela < relalim;  rela++) {
68	if (ELF_R_TYPE(rela->r_info) == R_X86_64_COPY) {
69	    void *dstaddr;
70	    const Elf_Sym *dstsym;
71	    const char *name;
72	    size_t size;
73	    const void *srcaddr;
74	    const Elf_Sym *srcsym;
75	    const Obj_Entry *srcobj, *defobj;
76	    SymLook req;
77	    int res;
78
79	    dstaddr = (void *) (dstobj->relocbase + rela->r_offset);
80	    dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info);
81	    name = dstobj->strtab + dstsym->st_name;
82	    size = dstsym->st_size;
83	    symlook_init(&req, name);
84	    req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info));
85	    req.flags = SYMLOOK_EARLY;
86
87	    for (srcobj = dstobj->next;  srcobj != NULL;  srcobj = srcobj->next) {
88		res = symlook_obj(&req, srcobj);
89		if (res == 0) {
90		    srcsym = req.sym_out;
91		    defobj = req.defobj_out;
92		    break;
93		}
94	    }
95
96	    if (srcobj == NULL) {
97		_rtld_error("Undefined symbol \"%s\" referenced from COPY"
98		  " relocation in %s", name, dstobj->path);
99		return -1;
100	    }
101
102	    srcaddr = (const void *) (defobj->relocbase + srcsym->st_value);
103	    memcpy(dstaddr, srcaddr, size);
104	}
105    }
106
107    return 0;
108}
109
110/* Initialize the special GOT entries. */
111void
112init_pltgot(Obj_Entry *obj)
113{
114    if (obj->pltgot != NULL) {
115	obj->pltgot[1] = (Elf_Addr) obj;
116	obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
117    }
118}
119
120/* Process the non-PLT relocations. */
121int
122reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
123    RtldLockState *lockstate)
124{
125	const Elf_Rela *relalim;
126	const Elf_Rela *rela;
127	SymCache *cache;
128	const Elf_Sym *def;
129	const Obj_Entry *defobj;
130	Elf_Addr *where, symval;
131	Elf32_Addr *where32;
132	int r;
133
134	r = -1;
135	/*
136	 * The dynamic loader may be called from a thread, we have
137	 * limited amounts of stack available so we cannot use alloca().
138	 */
139	if (obj != obj_rtld) {
140		cache = calloc(obj->dynsymcount, sizeof(SymCache));
141		/* No need to check for NULL here */
142	} else
143		cache = NULL;
144
145	relalim = (const Elf_Rela *)((caddr_t)obj->rela + obj->relasize);
146	for (rela = obj->rela;  rela < relalim;  rela++) {
147		/*
148		 * First, resolve symbol for relocations which
149		 * reference symbols.
150		 */
151		switch (ELF_R_TYPE(rela->r_info)) {
152		case R_X86_64_64:
153		case R_X86_64_PC32:
154		case R_X86_64_GLOB_DAT:
155		case R_X86_64_TPOFF64:
156		case R_X86_64_TPOFF32:
157		case R_X86_64_DTPMOD64:
158		case R_X86_64_DTPOFF64:
159		case R_X86_64_DTPOFF32:
160			def = find_symdef(ELF_R_SYM(rela->r_info), obj,
161			    &defobj, flags, cache, lockstate);
162			if (def == NULL)
163				goto done;
164			/*
165			 * If symbol is IFUNC, only perform relocation
166			 * when caller allowed it by passing
167			 * SYMLOOK_IFUNC flag.  Skip the relocations
168			 * otherwise.
169			 *
170			 * Also error out in case IFUNC relocations
171			 * are specified for TLS, which cannot be
172			 * usefully interpreted.
173			 */
174			if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
175				switch (ELF_R_TYPE(rela->r_info)) {
176				case R_X86_64_64:
177				case R_X86_64_PC32:
178				case R_X86_64_GLOB_DAT:
179					if ((flags & SYMLOOK_IFUNC) == 0) {
180						obj->non_plt_gnu_ifunc = true;
181						continue;
182					}
183					symval = (Elf_Addr)rtld_resolve_ifunc(
184					    defobj, def);
185					break;
186				case R_X86_64_TPOFF64:
187				case R_X86_64_TPOFF32:
188				case R_X86_64_DTPMOD64:
189				case R_X86_64_DTPOFF64:
190				case R_X86_64_DTPOFF32:
191					_rtld_error("%s: IFUNC for TLS reloc",
192					    obj->path);
193					goto done;
194				}
195			} else {
196				if ((flags & SYMLOOK_IFUNC) != 0)
197					continue;
198				symval = (Elf_Addr)defobj->relocbase +
199				    def->st_value;
200			}
201			break;
202		default:
203			if ((flags & SYMLOOK_IFUNC) != 0)
204				continue;
205			break;
206		}
207		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
208		where32 = (Elf32_Addr *)where;
209
210		switch (ELF_R_TYPE(rela->r_info)) {
211		case R_X86_64_NONE:
212			break;
213		case R_X86_64_64:
214			*where = symval + rela->r_addend;
215			break;
216		case R_X86_64_PC32:
217			/*
218			 * I don't think the dynamic linker should
219			 * ever see this type of relocation.  But the
220			 * binutils-2.6 tools sometimes generate it.
221			 */
222			*where32 = (Elf32_Addr)(unsigned long)(symval +
223		            rela->r_addend - (Elf_Addr)where);
224			break;
225		/* missing: R_X86_64_GOT32 R_X86_64_PLT32 */
226		case R_X86_64_COPY:
227			/*
228			 * These are deferred until all other relocations have
229			 * been done.  All we do here is make sure that the COPY
230			 * relocation is not in a shared library.  They are allowed
231			 * only in executable files.
232			 */
233			if (!obj->mainprog) {
234				_rtld_error("%s: Unexpected R_X86_64_COPY "
235				    "relocation in shared library", obj->path);
236				goto done;
237			}
238			break;
239		case R_X86_64_GLOB_DAT:
240			*where = symval;
241			break;
242		case R_X86_64_TPOFF64:
243			/*
244			 * We lazily allocate offsets for static TLS
245			 * as we see the first relocation that
246			 * references the TLS block. This allows us to
247			 * support (small amounts of) static TLS in
248			 * dynamically loaded modules. If we run out
249			 * of space, we generate an error.
250			 */
251			if (!defobj->tls_done) {
252				if (!allocate_tls_offset((Obj_Entry*) defobj)) {
253					_rtld_error("%s: No space available "
254					    "for static Thread Local Storage",
255					    obj->path);
256					goto done;
257				}
258			}
259			*where = (Elf_Addr)(def->st_value - defobj->tlsoffset +
260			    rela->r_addend);
261			break;
262		case R_X86_64_TPOFF32:
263			/*
264			 * We lazily allocate offsets for static TLS
265			 * as we see the first relocation that
266			 * references the TLS block. This allows us to
267			 * support (small amounts of) static TLS in
268			 * dynamically loaded modules. If we run out
269			 * of space, we generate an error.
270			 */
271			if (!defobj->tls_done) {
272				if (!allocate_tls_offset((Obj_Entry*) defobj)) {
273					_rtld_error("%s: No space available "
274					    "for static Thread Local Storage",
275					    obj->path);
276					goto done;
277				}
278			}
279			*where32 = (Elf32_Addr)(def->st_value -
280			    defobj->tlsoffset + rela->r_addend);
281			break;
282		case R_X86_64_DTPMOD64:
283			*where += (Elf_Addr)defobj->tlsindex;
284			break;
285		case R_X86_64_DTPOFF64:
286			*where += (Elf_Addr)(def->st_value + rela->r_addend);
287			break;
288		case R_X86_64_DTPOFF32:
289			*where32 += (Elf32_Addr)(def->st_value +
290			    rela->r_addend);
291			break;
292		case R_X86_64_RELATIVE:
293			*where = (Elf_Addr)(obj->relocbase + rela->r_addend);
294			break;
295		/*
296		 * missing:
297		 * R_X86_64_GOTPCREL, R_X86_64_32, R_X86_64_32S, R_X86_64_16,
298		 * R_X86_64_PC16, R_X86_64_8, R_X86_64_PC8
299		 */
300		default:
301			_rtld_error("%s: Unsupported relocation type %u"
302			    " in non-PLT relocations\n", obj->path,
303			    (unsigned int)ELF_R_TYPE(rela->r_info));
304			goto done;
305		}
306	}
307	r = 0;
308done:
309	free(cache);
310	return (r);
311}
312
313/* Process the PLT relocations. */
314int
315reloc_plt(Obj_Entry *obj)
316{
317    const Elf_Rela *relalim;
318    const Elf_Rela *rela;
319
320    relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize);
321    for (rela = obj->pltrela;  rela < relalim;  rela++) {
322	Elf_Addr *where;
323
324	switch(ELF_R_TYPE(rela->r_info)) {
325	case R_X86_64_JMP_SLOT:
326	  /* Relocate the GOT slot pointing into the PLT. */
327	  where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
328	  *where += (Elf_Addr)obj->relocbase;
329	  break;
330
331	case R_X86_64_IRELATIVE:
332	  obj->irelative = true;
333	  break;
334
335	default:
336	  _rtld_error("Unknown relocation type %x in PLT",
337	    (unsigned int)ELF_R_TYPE(rela->r_info));
338	  return (-1);
339	}
340    }
341    return 0;
342}
343
344/* Relocate the jump slots in an object. */
345int
346reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
347{
348    const Elf_Rela *relalim;
349    const Elf_Rela *rela;
350
351    if (obj->jmpslots_done)
352	return 0;
353    relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize);
354    for (rela = obj->pltrela;  rela < relalim;  rela++) {
355	Elf_Addr *where, target;
356	const Elf_Sym *def;
357	const Obj_Entry *defobj;
358
359	switch (ELF_R_TYPE(rela->r_info)) {
360	case R_X86_64_JMP_SLOT:
361	  where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
362	  def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
363		SYMLOOK_IN_PLT | flags, NULL, lockstate);
364	  if (def == NULL)
365	      return (-1);
366	  if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
367	      obj->gnu_ifunc = true;
368	      continue;
369	  }
370	  target = (Elf_Addr)(defobj->relocbase + def->st_value + rela->r_addend);
371	  reloc_jmpslot(where, target, defobj, obj, (const Elf_Rel *)rela);
372	  break;
373
374	case R_X86_64_IRELATIVE:
375	  break;
376
377	default:
378	  _rtld_error("Unknown relocation type %x in PLT",
379	    (unsigned int)ELF_R_TYPE(rela->r_info));
380	  return (-1);
381	}
382    }
383    obj->jmpslots_done = true;
384    return 0;
385}
386
387int
388reloc_iresolve(Obj_Entry *obj, RtldLockState *lockstate)
389{
390    const Elf_Rela *relalim;
391    const Elf_Rela *rela;
392
393    if (!obj->irelative)
394	return (0);
395    relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize);
396    for (rela = obj->pltrela;  rela < relalim;  rela++) {
397	Elf_Addr *where, target, *ptr;
398
399	switch (ELF_R_TYPE(rela->r_info)) {
400	case R_X86_64_JMP_SLOT:
401	  break;
402
403	case R_X86_64_IRELATIVE:
404	  ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend);
405	  where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
406	  lock_release(rtld_bind_lock, lockstate);
407	  target = ((Elf_Addr (*)(void))ptr)();
408	  wlock_acquire(rtld_bind_lock, lockstate);
409	  *where = target;
410	  break;
411	}
412    }
413    obj->irelative = false;
414    return (0);
415}
416
417int
418reloc_gnu_ifunc(Obj_Entry *obj, int flags, RtldLockState *lockstate)
419{
420    const Elf_Rela *relalim;
421    const Elf_Rela *rela;
422
423    if (!obj->gnu_ifunc)
424	return (0);
425    relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize);
426    for (rela = obj->pltrela;  rela < relalim;  rela++) {
427	Elf_Addr *where, target;
428	const Elf_Sym *def;
429	const Obj_Entry *defobj;
430
431	switch (ELF_R_TYPE(rela->r_info)) {
432	case R_X86_64_JMP_SLOT:
433	  where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
434	  def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
435		SYMLOOK_IN_PLT | flags, NULL, lockstate);
436	  if (def == NULL)
437	      return (-1);
438	  if (ELF_ST_TYPE(def->st_info) != STT_GNU_IFUNC)
439	      continue;
440	  lock_release(rtld_bind_lock, lockstate);
441	  target = (Elf_Addr)rtld_resolve_ifunc(defobj, def);
442	  wlock_acquire(rtld_bind_lock, lockstate);
443	  reloc_jmpslot(where, target, defobj, obj, (const Elf_Rel *)rela);
444	  break;
445	}
446    }
447    obj->gnu_ifunc = false;
448    return (0);
449}
450
451void
452allocate_initial_tls(Obj_Entry *objs)
453{
454    /*
455     * Fix the size of the static TLS block by using the maximum
456     * offset allocated so far and adding a bit for dynamic modules to
457     * use.
458     */
459    tls_static_space = tls_last_offset + RTLD_STATIC_TLS_EXTRA;
460    amd64_set_fsbase(allocate_tls(objs, 0,
461				  3*sizeof(Elf_Addr), sizeof(Elf_Addr)));
462}
463
464void *__tls_get_addr(tls_index *ti)
465{
466    Elf_Addr** segbase;
467
468    __asm __volatile("movq %%fs:0, %0" : "=r" (segbase));
469
470    return tls_get_addr_common(&segbase[1], ti->ti_module, ti->ti_offset);
471}
472