138816Sdfr/*-
248205Sjdp * Copyright 1996, 1997, 1998, 1999 John D. Polstra.
338816Sdfr * All rights reserved.
438816Sdfr *
538816Sdfr * Redistribution and use in source and binary forms, with or without
638816Sdfr * modification, are permitted provided that the following conditions
738816Sdfr * are met:
838816Sdfr * 1. Redistributions of source code must retain the above copyright
938816Sdfr *    notice, this list of conditions and the following disclaimer.
1038816Sdfr * 2. Redistributions in binary form must reproduce the above copyright
1138816Sdfr *    notice, this list of conditions and the following disclaimer in the
1238816Sdfr *    documentation and/or other materials provided with the distribution.
1338816Sdfr *
1438816Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1538816Sdfr * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1638816Sdfr * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1738816Sdfr * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1838816Sdfr * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1938816Sdfr * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2038816Sdfr * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2138816Sdfr * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2238816Sdfr * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2338816Sdfr * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2438816Sdfr *
2550476Speter * $FreeBSD: releng/10.3/libexec/rtld-elf/amd64/reloc.c 281453 2015-04-12 06:45:40Z kib $
2638816Sdfr */
2738816Sdfr
2838816Sdfr/*
2938816Sdfr * Dynamic linker for ELF.
3038816Sdfr *
3138816Sdfr * John Polstra <jdp@polstra.com>.
3238816Sdfr */
3338816Sdfr
3438816Sdfr#include <sys/param.h>
3538816Sdfr#include <sys/mman.h>
36133063Sdfr#include <machine/sysarch.h>
3738816Sdfr
3838816Sdfr#include <dlfcn.h>
3938816Sdfr#include <err.h>
4038816Sdfr#include <errno.h>
4138816Sdfr#include <fcntl.h>
4238816Sdfr#include <stdarg.h>
4338816Sdfr#include <stdio.h>
4438816Sdfr#include <stdlib.h>
4538816Sdfr#include <string.h>
4638816Sdfr#include <unistd.h>
4738816Sdfr
4838816Sdfr#include "debug.h"
4938816Sdfr#include "rtld.h"
50281453Skib#include "rtld_tls.h"
5138816Sdfr
5238816Sdfr/*
53115280Speter * Process the special R_X86_64_COPY relocations in the main program.  These
5438816Sdfr * copy data from a shared object into a region in the main program's BSS
5538816Sdfr * segment.
5638816Sdfr *
5738816Sdfr * Returns 0 on success, -1 on failure.
5838816Sdfr */
5938816Sdfrint
6038816Sdfrdo_copy_relocations(Obj_Entry *dstobj)
6138816Sdfr{
62115280Speter    const Elf_Rela *relalim;
63115280Speter    const Elf_Rela *rela;
6438816Sdfr
6538816Sdfr    assert(dstobj->mainprog);	/* COPY relocations are invalid elsewhere */
6638816Sdfr
67115280Speter    relalim = (const Elf_Rela *) ((caddr_t) dstobj->rela + dstobj->relasize);
68115280Speter    for (rela = dstobj->rela;  rela < relalim;  rela++) {
69115280Speter	if (ELF_R_TYPE(rela->r_info) == R_X86_64_COPY) {
7038816Sdfr	    void *dstaddr;
7138816Sdfr	    const Elf_Sym *dstsym;
7238816Sdfr	    const char *name;
7338816Sdfr	    size_t size;
7438816Sdfr	    const void *srcaddr;
7538816Sdfr	    const Elf_Sym *srcsym;
76216695Skib	    const Obj_Entry *srcobj, *defobj;
77216695Skib	    SymLook req;
78216695Skib	    int res;
7938816Sdfr
80115280Speter	    dstaddr = (void *) (dstobj->relocbase + rela->r_offset);
81115280Speter	    dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info);
8238816Sdfr	    name = dstobj->strtab + dstsym->st_name;
8338816Sdfr	    size = dstsym->st_size;
84216695Skib	    symlook_init(&req, name);
85216695Skib	    req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info));
86233231Skib	    req.flags = SYMLOOK_EARLY;
8738816Sdfr
88216695Skib	    for (srcobj = dstobj->next;  srcobj != NULL;  srcobj = srcobj->next) {
89216695Skib		res = symlook_obj(&req, srcobj);
90216695Skib		if (res == 0) {
91216695Skib		    srcsym = req.sym_out;
92216695Skib		    defobj = req.defobj_out;
9338816Sdfr		    break;
94216695Skib		}
95216695Skib	    }
9638816Sdfr
9738816Sdfr	    if (srcobj == NULL) {
9838816Sdfr		_rtld_error("Undefined symbol \"%s\" referenced from COPY"
9938816Sdfr		  " relocation in %s", name, dstobj->path);
10038816Sdfr		return -1;
10138816Sdfr	    }
10238816Sdfr
103216695Skib	    srcaddr = (const void *) (defobj->relocbase + srcsym->st_value);
10438816Sdfr	    memcpy(dstaddr, srcaddr, size);
10538816Sdfr	}
10638816Sdfr    }
10738816Sdfr
10838816Sdfr    return 0;
10938816Sdfr}
11038816Sdfr
11145501Sjdp/* Initialize the special GOT entries. */
11245501Sjdpvoid
11345501Sjdpinit_pltgot(Obj_Entry *obj)
11445501Sjdp{
11545501Sjdp    if (obj->pltgot != NULL) {
11645501Sjdp	obj->pltgot[1] = (Elf_Addr) obj;
11745501Sjdp	obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
11845501Sjdp    }
11945501Sjdp}
12045501Sjdp
12138816Sdfr/* Process the non-PLT relocations. */
12238816Sdfrint
123233231Skibreloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
124233231Skib    RtldLockState *lockstate)
12538816Sdfr{
126115280Speter	const Elf_Rela *relalim;
127115280Speter	const Elf_Rela *rela;
12876296Sjdp	SymCache *cache;
129271469Skib	const Elf_Sym *def;
130271469Skib	const Obj_Entry *defobj;
131271469Skib	Elf_Addr *where, symval;
132271469Skib	Elf32_Addr *where32;
133271469Skib	int r;
13438816Sdfr
135271469Skib	r = -1;
13698100Sdillon	/*
13798100Sdillon	 * The dynamic loader may be called from a thread, we have
13898100Sdillon	 * limited amounts of stack available so we cannot use alloca().
13998100Sdillon	 */
140208256Srdivacky	if (obj != obj_rtld) {
141271469Skib		cache = calloc(obj->dynsymcount, sizeof(SymCache));
142271469Skib		/* No need to check for NULL here */
143208256Srdivacky	} else
144271469Skib		cache = NULL;
14576296Sjdp
146271469Skib	relalim = (const Elf_Rela *)((caddr_t)obj->rela + obj->relasize);
147115280Speter	for (rela = obj->rela;  rela < relalim;  rela++) {
14838816Sdfr		/*
149271469Skib		 * First, resolve symbol for relocations which
150271469Skib		 * reference symbols.
15138816Sdfr		 */
152271469Skib		switch (ELF_R_TYPE(rela->r_info)) {
153271469Skib		case R_X86_64_64:
154271469Skib		case R_X86_64_PC32:
155271469Skib		case R_X86_64_GLOB_DAT:
156271469Skib		case R_X86_64_TPOFF64:
157271469Skib		case R_X86_64_TPOFF32:
158271469Skib		case R_X86_64_DTPMOD64:
159271469Skib		case R_X86_64_DTPOFF64:
160271469Skib		case R_X86_64_DTPOFF32:
161271469Skib			def = find_symdef(ELF_R_SYM(rela->r_info), obj,
162271469Skib			    &defobj, flags, cache, lockstate);
163271469Skib			if (def == NULL)
164271469Skib				goto done;
165271469Skib			/*
166271469Skib			 * If symbol is IFUNC, only perform relocation
167271469Skib			 * when caller allowed it by passing
168271469Skib			 * SYMLOOK_IFUNC flag.  Skip the relocations
169271469Skib			 * otherwise.
170271469Skib			 *
171271469Skib			 * Also error out in case IFUNC relocations
172271469Skib			 * are specified for TLS, which cannot be
173271469Skib			 * usefully interpreted.
174271469Skib			 */
175271469Skib			if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
176271469Skib				switch (ELF_R_TYPE(rela->r_info)) {
177271469Skib				case R_X86_64_64:
178271469Skib				case R_X86_64_PC32:
179271469Skib				case R_X86_64_GLOB_DAT:
180271469Skib					if ((flags & SYMLOOK_IFUNC) == 0) {
181271469Skib						obj->non_plt_gnu_ifunc = true;
182271469Skib						continue;
183271469Skib					}
184271469Skib					symval = (Elf_Addr)rtld_resolve_ifunc(
185271469Skib					    defobj, def);
186271469Skib					break;
187271469Skib				case R_X86_64_TPOFF64:
188271469Skib				case R_X86_64_TPOFF32:
189271469Skib				case R_X86_64_DTPMOD64:
190271469Skib				case R_X86_64_DTPOFF64:
191271469Skib				case R_X86_64_DTPOFF32:
192271469Skib					_rtld_error("%s: IFUNC for TLS reloc",
193271469Skib					    obj->path);
194271469Skib					goto done;
195271469Skib				}
196271469Skib			} else {
197271469Skib				if ((flags & SYMLOOK_IFUNC) != 0)
198271469Skib					continue;
199271469Skib				symval = (Elf_Addr)defobj->relocbase +
200271469Skib				    def->st_value;
201271469Skib			}
202271469Skib			break;
203271469Skib		default:
204271469Skib			if ((flags & SYMLOOK_IFUNC) != 0)
205271469Skib				continue;
206271469Skib			break;
20738816Sdfr		}
208271469Skib		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
209271469Skib		where32 = (Elf32_Addr *)where;
21038816Sdfr
211271469Skib		switch (ELF_R_TYPE(rela->r_info)) {
212271469Skib		case R_X86_64_NONE:
213271469Skib			break;
214271469Skib		case R_X86_64_64:
215271469Skib			*where = symval + rela->r_addend;
216271469Skib			break;
217271469Skib		case R_X86_64_PC32:
218271469Skib			/*
219271469Skib			 * I don't think the dynamic linker should
220271469Skib			 * ever see this type of relocation.  But the
221271469Skib			 * binutils-2.6 tools sometimes generate it.
222271469Skib			 */
223271469Skib			*where32 = (Elf32_Addr)(unsigned long)(symval +
224271469Skib		            rela->r_addend - (Elf_Addr)where);
225271469Skib			break;
226271469Skib		/* missing: R_X86_64_GOT32 R_X86_64_PLT32 */
227271469Skib		case R_X86_64_COPY:
228271469Skib			/*
229271469Skib			 * These are deferred until all other relocations have
230271469Skib			 * been done.  All we do here is make sure that the COPY
231271469Skib			 * relocation is not in a shared library.  They are allowed
232271469Skib			 * only in executable files.
233271469Skib			 */
234271469Skib			if (!obj->mainprog) {
235271469Skib				_rtld_error("%s: Unexpected R_X86_64_COPY "
236271469Skib				    "relocation in shared library", obj->path);
237271469Skib				goto done;
238271469Skib			}
239271469Skib			break;
240271469Skib		case R_X86_64_GLOB_DAT:
241271469Skib			*where = symval;
242271469Skib			break;
243271469Skib		case R_X86_64_TPOFF64:
244271469Skib			/*
245271469Skib			 * We lazily allocate offsets for static TLS
246271469Skib			 * as we see the first relocation that
247271469Skib			 * references the TLS block. This allows us to
248271469Skib			 * support (small amounts of) static TLS in
249271469Skib			 * dynamically loaded modules. If we run out
250271469Skib			 * of space, we generate an error.
251271469Skib			 */
252271469Skib			if (!defobj->tls_done) {
253271469Skib				if (!allocate_tls_offset((Obj_Entry*) defobj)) {
254271469Skib					_rtld_error("%s: No space available "
255271469Skib					    "for static Thread Local Storage",
256271469Skib					    obj->path);
257271469Skib					goto done;
258271469Skib				}
259271469Skib			}
260271469Skib			*where = (Elf_Addr)(def->st_value - defobj->tlsoffset +
261271469Skib			    rela->r_addend);
262271469Skib			break;
263271469Skib		case R_X86_64_TPOFF32:
264271469Skib			/*
265271469Skib			 * We lazily allocate offsets for static TLS
266271469Skib			 * as we see the first relocation that
267271469Skib			 * references the TLS block. This allows us to
268271469Skib			 * support (small amounts of) static TLS in
269271469Skib			 * dynamically loaded modules. If we run out
270271469Skib			 * of space, we generate an error.
271271469Skib			 */
272271469Skib			if (!defobj->tls_done) {
273271469Skib				if (!allocate_tls_offset((Obj_Entry*) defobj)) {
274271469Skib					_rtld_error("%s: No space available "
275271469Skib					    "for static Thread Local Storage",
276271469Skib					    obj->path);
277271469Skib					goto done;
278271469Skib				}
279271469Skib			}
280271469Skib			*where32 = (Elf32_Addr)(def->st_value -
281271469Skib			    defobj->tlsoffset + rela->r_addend);
282271469Skib			break;
283271469Skib		case R_X86_64_DTPMOD64:
284271469Skib			*where += (Elf_Addr)defobj->tlsindex;
285271469Skib			break;
286271469Skib		case R_X86_64_DTPOFF64:
287271469Skib			*where += (Elf_Addr)(def->st_value + rela->r_addend);
288271469Skib			break;
289271469Skib		case R_X86_64_DTPOFF32:
290271469Skib			*where32 += (Elf32_Addr)(def->st_value +
291271469Skib			    rela->r_addend);
292271469Skib			break;
293271469Skib		case R_X86_64_RELATIVE:
294271469Skib			*where = (Elf_Addr)(obj->relocbase + rela->r_addend);
295271469Skib			break;
29638816Sdfr		/*
297271469Skib		 * missing:
298271469Skib		 * R_X86_64_GOTPCREL, R_X86_64_32, R_X86_64_32S, R_X86_64_16,
299271469Skib		 * R_X86_64_PC16, R_X86_64_8, R_X86_64_PC8
30038816Sdfr		 */
301271469Skib		default:
302271469Skib			_rtld_error("%s: Unsupported relocation type %u"
303271469Skib			    " in non-PLT relocations\n", obj->path,
304271469Skib			    (unsigned int)ELF_R_TYPE(rela->r_info));
30598100Sdillon			goto done;
30638816Sdfr		}
30738816Sdfr	}
30898103Sdillon	r = 0;
30998103Sdillondone:
310271469Skib	free(cache);
311233231Skib	return (r);
31238816Sdfr}
31338816Sdfr
31438816Sdfr/* Process the PLT relocations. */
31538816Sdfrint
31656780Sjdpreloc_plt(Obj_Entry *obj)
31738816Sdfr{
318115280Speter    const Elf_Rela *relalim;
319115280Speter    const Elf_Rela *rela;
32038816Sdfr
321115280Speter    relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize);
322115280Speter    for (rela = obj->pltrela;  rela < relalim;  rela++) {
32348205Sjdp	Elf_Addr *where;
32438816Sdfr
325228435Skib	switch(ELF_R_TYPE(rela->r_info)) {
326228435Skib	case R_X86_64_JMP_SLOT:
327228435Skib	  /* Relocate the GOT slot pointing into the PLT. */
328228435Skib	  where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
329228435Skib	  *where += (Elf_Addr)obj->relocbase;
330228435Skib	  break;
33138816Sdfr
332228435Skib	case R_X86_64_IRELATIVE:
333228435Skib	  obj->irelative = true;
334228435Skib	  break;
335228435Skib
336228435Skib	default:
337228435Skib	  _rtld_error("Unknown relocation type %x in PLT",
338228435Skib	    (unsigned int)ELF_R_TYPE(rela->r_info));
339228435Skib	  return (-1);
340228435Skib	}
34156780Sjdp    }
34256780Sjdp    return 0;
34356780Sjdp}
34438816Sdfr
34556780Sjdp/* Relocate the jump slots in an object. */
34656780Sjdpint
347233231Skibreloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
34856780Sjdp{
349115280Speter    const Elf_Rela *relalim;
350115280Speter    const Elf_Rela *rela;
35148205Sjdp
35256780Sjdp    if (obj->jmpslots_done)
35356780Sjdp	return 0;
354115280Speter    relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize);
355115280Speter    for (rela = obj->pltrela;  rela < relalim;  rela++) {
35685004Sdfr	Elf_Addr *where, target;
35756780Sjdp	const Elf_Sym *def;
35856780Sjdp	const Obj_Entry *defobj;
35956780Sjdp
360228435Skib	switch (ELF_R_TYPE(rela->r_info)) {
361228435Skib	case R_X86_64_JMP_SLOT:
362228435Skib	  where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
363233231Skib	  def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
364233231Skib		SYMLOOK_IN_PLT | flags, NULL, lockstate);
365228435Skib	  if (def == NULL)
366228435Skib	      return (-1);
367228435Skib	  if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
368228435Skib	      obj->gnu_ifunc = true;
369228435Skib	      continue;
370228435Skib	  }
371228435Skib	  target = (Elf_Addr)(defobj->relocbase + def->st_value + rela->r_addend);
372228435Skib	  reloc_jmpslot(where, target, defobj, obj, (const Elf_Rel *)rela);
373228435Skib	  break;
374228435Skib
375228435Skib	case R_X86_64_IRELATIVE:
376228435Skib	  break;
377228435Skib
378228435Skib	default:
379228435Skib	  _rtld_error("Unknown relocation type %x in PLT",
380228435Skib	    (unsigned int)ELF_R_TYPE(rela->r_info));
381228435Skib	  return (-1);
382228435Skib	}
38348205Sjdp    }
38456780Sjdp    obj->jmpslots_done = true;
38538816Sdfr    return 0;
38638816Sdfr}
387133063Sdfr
388228435Skibint
389228435Skibreloc_iresolve(Obj_Entry *obj, RtldLockState *lockstate)
390228435Skib{
391228435Skib    const Elf_Rela *relalim;
392228435Skib    const Elf_Rela *rela;
393228435Skib
394228503Skib    if (!obj->irelative)
395228503Skib	return (0);
396228435Skib    relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize);
397228435Skib    for (rela = obj->pltrela;  rela < relalim;  rela++) {
398228435Skib	Elf_Addr *where, target, *ptr;
399228435Skib
400228435Skib	switch (ELF_R_TYPE(rela->r_info)) {
401228435Skib	case R_X86_64_JMP_SLOT:
402228435Skib	  break;
403228435Skib
404228435Skib	case R_X86_64_IRELATIVE:
405228435Skib	  ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend);
406228435Skib	  where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
407228503Skib	  lock_release(rtld_bind_lock, lockstate);
408228435Skib	  target = ((Elf_Addr (*)(void))ptr)();
409228503Skib	  wlock_acquire(rtld_bind_lock, lockstate);
410228435Skib	  *where = target;
411228435Skib	  break;
412228435Skib	}
413228435Skib    }
414228503Skib    obj->irelative = false;
415228435Skib    return (0);
416228435Skib}
417228435Skib
418228435Skibint
419233231Skibreloc_gnu_ifunc(Obj_Entry *obj, int flags, RtldLockState *lockstate)
420228435Skib{
421228435Skib    const Elf_Rela *relalim;
422228435Skib    const Elf_Rela *rela;
423228435Skib
424228435Skib    if (!obj->gnu_ifunc)
425228435Skib	return (0);
426228435Skib    relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize);
427228435Skib    for (rela = obj->pltrela;  rela < relalim;  rela++) {
428228435Skib	Elf_Addr *where, target;
429228435Skib	const Elf_Sym *def;
430228435Skib	const Obj_Entry *defobj;
431228435Skib
432228435Skib	switch (ELF_R_TYPE(rela->r_info)) {
433228435Skib	case R_X86_64_JMP_SLOT:
434228435Skib	  where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
435233231Skib	  def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
436233231Skib		SYMLOOK_IN_PLT | flags, NULL, lockstate);
437228435Skib	  if (def == NULL)
438228435Skib	      return (-1);
439228435Skib	  if (ELF_ST_TYPE(def->st_info) != STT_GNU_IFUNC)
440228435Skib	      continue;
441228503Skib	  lock_release(rtld_bind_lock, lockstate);
442228435Skib	  target = (Elf_Addr)rtld_resolve_ifunc(defobj, def);
443228503Skib	  wlock_acquire(rtld_bind_lock, lockstate);
444228435Skib	  reloc_jmpslot(where, target, defobj, obj, (const Elf_Rel *)rela);
445228435Skib	  break;
446228435Skib	}
447228435Skib    }
448228435Skib    obj->gnu_ifunc = false;
449228503Skib    return (0);
450228435Skib}
451228435Skib
452133063Sdfrvoid
453133063Sdfrallocate_initial_tls(Obj_Entry *objs)
454133063Sdfr{
455133063Sdfr    /*
456133063Sdfr     * Fix the size of the static TLS block by using the maximum
457133063Sdfr     * offset allocated so far and adding a bit for dynamic modules to
458133063Sdfr     * use.
459133063Sdfr     */
460133063Sdfr    tls_static_space = tls_last_offset + RTLD_STATIC_TLS_EXTRA;
461133063Sdfr    amd64_set_fsbase(allocate_tls(objs, 0,
462157198Sdavidxu				  3*sizeof(Elf_Addr), sizeof(Elf_Addr)));
463133063Sdfr}
464133063Sdfr
465133063Sdfrvoid *__tls_get_addr(tls_index *ti)
466133063Sdfr{
467133063Sdfr    Elf_Addr** segbase;
468133063Sdfr
469133063Sdfr    __asm __volatile("movq %%fs:0, %0" : "=r" (segbase));
470133063Sdfr
471133063Sdfr    return tls_get_addr_common(&segbase[1], ti->ti_module, ti->ti_offset);
472133063Sdfr}
473