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$
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"
5038816Sdfr
5138816Sdfr/*
52115280Speter * Process the special R_X86_64_COPY relocations in the main program.  These
5338816Sdfr * copy data from a shared object into a region in the main program's BSS
5438816Sdfr * segment.
5538816Sdfr *
5638816Sdfr * Returns 0 on success, -1 on failure.
5738816Sdfr */
5838816Sdfrint
5938816Sdfrdo_copy_relocations(Obj_Entry *dstobj)
6038816Sdfr{
61115280Speter    const Elf_Rela *relalim;
62115280Speter    const Elf_Rela *rela;
6338816Sdfr
6438816Sdfr    assert(dstobj->mainprog);	/* COPY relocations are invalid elsewhere */
6538816Sdfr
66115280Speter    relalim = (const Elf_Rela *) ((caddr_t) dstobj->rela + dstobj->relasize);
67115280Speter    for (rela = dstobj->rela;  rela < relalim;  rela++) {
68115280Speter	if (ELF_R_TYPE(rela->r_info) == R_X86_64_COPY) {
6938816Sdfr	    void *dstaddr;
7038816Sdfr	    const Elf_Sym *dstsym;
7138816Sdfr	    const char *name;
7238816Sdfr	    size_t size;
7338816Sdfr	    const void *srcaddr;
7438816Sdfr	    const Elf_Sym *srcsym;
75216695Skib	    const Obj_Entry *srcobj, *defobj;
76216695Skib	    SymLook req;
77216695Skib	    int res;
7838816Sdfr
79115280Speter	    dstaddr = (void *) (dstobj->relocbase + rela->r_offset);
80115280Speter	    dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info);
8138816Sdfr	    name = dstobj->strtab + dstsym->st_name;
8238816Sdfr	    size = dstsym->st_size;
83216695Skib	    symlook_init(&req, name);
84216695Skib	    req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info));
85233231Skib	    req.flags = SYMLOOK_EARLY;
8638816Sdfr
87216695Skib	    for (srcobj = dstobj->next;  srcobj != NULL;  srcobj = srcobj->next) {
88216695Skib		res = symlook_obj(&req, srcobj);
89216695Skib		if (res == 0) {
90216695Skib		    srcsym = req.sym_out;
91216695Skib		    defobj = req.defobj_out;
9238816Sdfr		    break;
93216695Skib		}
94216695Skib	    }
9538816Sdfr
9638816Sdfr	    if (srcobj == NULL) {
9738816Sdfr		_rtld_error("Undefined symbol \"%s\" referenced from COPY"
9838816Sdfr		  " relocation in %s", name, dstobj->path);
9938816Sdfr		return -1;
10038816Sdfr	    }
10138816Sdfr
102216695Skib	    srcaddr = (const void *) (defobj->relocbase + srcsym->st_value);
10338816Sdfr	    memcpy(dstaddr, srcaddr, size);
10438816Sdfr	}
10538816Sdfr    }
10638816Sdfr
10738816Sdfr    return 0;
10838816Sdfr}
10938816Sdfr
11045501Sjdp/* Initialize the special GOT entries. */
11145501Sjdpvoid
11245501Sjdpinit_pltgot(Obj_Entry *obj)
11345501Sjdp{
11445501Sjdp    if (obj->pltgot != NULL) {
11545501Sjdp	obj->pltgot[1] = (Elf_Addr) obj;
11645501Sjdp	obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
11745501Sjdp    }
11845501Sjdp}
11945501Sjdp
12038816Sdfr/* Process the non-PLT relocations. */
12138816Sdfrint
122233231Skibreloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
123233231Skib    RtldLockState *lockstate)
12438816Sdfr{
125115280Speter	const Elf_Rela *relalim;
126115280Speter	const Elf_Rela *rela;
12776296Sjdp	SymCache *cache;
128271469Skib	const Elf_Sym *def;
129271469Skib	const Obj_Entry *defobj;
130271469Skib	Elf_Addr *where, symval;
131271469Skib	Elf32_Addr *where32;
132271469Skib	int r;
13338816Sdfr
134271469Skib	r = -1;
13598100Sdillon	/*
13698100Sdillon	 * The dynamic loader may be called from a thread, we have
13798100Sdillon	 * limited amounts of stack available so we cannot use alloca().
13898100Sdillon	 */
139208256Srdivacky	if (obj != obj_rtld) {
140271469Skib		cache = calloc(obj->dynsymcount, sizeof(SymCache));
141271469Skib		/* No need to check for NULL here */
142208256Srdivacky	} else
143271469Skib		cache = NULL;
14476296Sjdp
145271469Skib	relalim = (const Elf_Rela *)((caddr_t)obj->rela + obj->relasize);
146115280Speter	for (rela = obj->rela;  rela < relalim;  rela++) {
14738816Sdfr		/*
148271469Skib		 * First, resolve symbol for relocations which
149271469Skib		 * reference symbols.
15038816Sdfr		 */
151271469Skib		switch (ELF_R_TYPE(rela->r_info)) {
152271469Skib		case R_X86_64_64:
153271469Skib		case R_X86_64_PC32:
154271469Skib		case R_X86_64_GLOB_DAT:
155271469Skib		case R_X86_64_TPOFF64:
156271469Skib		case R_X86_64_TPOFF32:
157271469Skib		case R_X86_64_DTPMOD64:
158271469Skib		case R_X86_64_DTPOFF64:
159271469Skib		case R_X86_64_DTPOFF32:
160271469Skib			def = find_symdef(ELF_R_SYM(rela->r_info), obj,
161271469Skib			    &defobj, flags, cache, lockstate);
162271469Skib			if (def == NULL)
163271469Skib				goto done;
164271469Skib			/*
165271469Skib			 * If symbol is IFUNC, only perform relocation
166271469Skib			 * when caller allowed it by passing
167271469Skib			 * SYMLOOK_IFUNC flag.  Skip the relocations
168271469Skib			 * otherwise.
169271469Skib			 *
170271469Skib			 * Also error out in case IFUNC relocations
171271469Skib			 * are specified for TLS, which cannot be
172271469Skib			 * usefully interpreted.
173271469Skib			 */
174271469Skib			if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
175271469Skib				switch (ELF_R_TYPE(rela->r_info)) {
176271469Skib				case R_X86_64_64:
177271469Skib				case R_X86_64_PC32:
178271469Skib				case R_X86_64_GLOB_DAT:
179271469Skib					if ((flags & SYMLOOK_IFUNC) == 0) {
180271469Skib						obj->non_plt_gnu_ifunc = true;
181271469Skib						continue;
182271469Skib					}
183271469Skib					symval = (Elf_Addr)rtld_resolve_ifunc(
184271469Skib					    defobj, def);
185271469Skib					break;
186271469Skib				case R_X86_64_TPOFF64:
187271469Skib				case R_X86_64_TPOFF32:
188271469Skib				case R_X86_64_DTPMOD64:
189271469Skib				case R_X86_64_DTPOFF64:
190271469Skib				case R_X86_64_DTPOFF32:
191271469Skib					_rtld_error("%s: IFUNC for TLS reloc",
192271469Skib					    obj->path);
193271469Skib					goto done;
194271469Skib				}
195271469Skib			} else {
196271469Skib				if ((flags & SYMLOOK_IFUNC) != 0)
197271469Skib					continue;
198271469Skib				symval = (Elf_Addr)defobj->relocbase +
199271469Skib				    def->st_value;
200271469Skib			}
201271469Skib			break;
202271469Skib		default:
203271469Skib			if ((flags & SYMLOOK_IFUNC) != 0)
204271469Skib				continue;
205271469Skib			break;
20638816Sdfr		}
207271469Skib		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
208271469Skib		where32 = (Elf32_Addr *)where;
20938816Sdfr
210271469Skib		switch (ELF_R_TYPE(rela->r_info)) {
211271469Skib		case R_X86_64_NONE:
212271469Skib			break;
213271469Skib		case R_X86_64_64:
214271469Skib			*where = symval + rela->r_addend;
215271469Skib			break;
216271469Skib		case R_X86_64_PC32:
217271469Skib			/*
218271469Skib			 * I don't think the dynamic linker should
219271469Skib			 * ever see this type of relocation.  But the
220271469Skib			 * binutils-2.6 tools sometimes generate it.
221271469Skib			 */
222271469Skib			*where32 = (Elf32_Addr)(unsigned long)(symval +
223271469Skib		            rela->r_addend - (Elf_Addr)where);
224271469Skib			break;
225271469Skib		/* missing: R_X86_64_GOT32 R_X86_64_PLT32 */
226271469Skib		case R_X86_64_COPY:
227271469Skib			/*
228271469Skib			 * These are deferred until all other relocations have
229271469Skib			 * been done.  All we do here is make sure that the COPY
230271469Skib			 * relocation is not in a shared library.  They are allowed
231271469Skib			 * only in executable files.
232271469Skib			 */
233271469Skib			if (!obj->mainprog) {
234271469Skib				_rtld_error("%s: Unexpected R_X86_64_COPY "
235271469Skib				    "relocation in shared library", obj->path);
236271469Skib				goto done;
237271469Skib			}
238271469Skib			break;
239271469Skib		case R_X86_64_GLOB_DAT:
240271469Skib			*where = symval;
241271469Skib			break;
242271469Skib		case R_X86_64_TPOFF64:
243271469Skib			/*
244271469Skib			 * We lazily allocate offsets for static TLS
245271469Skib			 * as we see the first relocation that
246271469Skib			 * references the TLS block. This allows us to
247271469Skib			 * support (small amounts of) static TLS in
248271469Skib			 * dynamically loaded modules. If we run out
249271469Skib			 * of space, we generate an error.
250271469Skib			 */
251271469Skib			if (!defobj->tls_done) {
252271469Skib				if (!allocate_tls_offset((Obj_Entry*) defobj)) {
253271469Skib					_rtld_error("%s: No space available "
254271469Skib					    "for static Thread Local Storage",
255271469Skib					    obj->path);
256271469Skib					goto done;
257271469Skib				}
258271469Skib			}
259271469Skib			*where = (Elf_Addr)(def->st_value - defobj->tlsoffset +
260271469Skib			    rela->r_addend);
261271469Skib			break;
262271469Skib		case R_X86_64_TPOFF32:
263271469Skib			/*
264271469Skib			 * We lazily allocate offsets for static TLS
265271469Skib			 * as we see the first relocation that
266271469Skib			 * references the TLS block. This allows us to
267271469Skib			 * support (small amounts of) static TLS in
268271469Skib			 * dynamically loaded modules. If we run out
269271469Skib			 * of space, we generate an error.
270271469Skib			 */
271271469Skib			if (!defobj->tls_done) {
272271469Skib				if (!allocate_tls_offset((Obj_Entry*) defobj)) {
273271469Skib					_rtld_error("%s: No space available "
274271469Skib					    "for static Thread Local Storage",
275271469Skib					    obj->path);
276271469Skib					goto done;
277271469Skib				}
278271469Skib			}
279271469Skib			*where32 = (Elf32_Addr)(def->st_value -
280271469Skib			    defobj->tlsoffset + rela->r_addend);
281271469Skib			break;
282271469Skib		case R_X86_64_DTPMOD64:
283271469Skib			*where += (Elf_Addr)defobj->tlsindex;
284271469Skib			break;
285271469Skib		case R_X86_64_DTPOFF64:
286271469Skib			*where += (Elf_Addr)(def->st_value + rela->r_addend);
287271469Skib			break;
288271469Skib		case R_X86_64_DTPOFF32:
289271469Skib			*where32 += (Elf32_Addr)(def->st_value +
290271469Skib			    rela->r_addend);
291271469Skib			break;
292271469Skib		case R_X86_64_RELATIVE:
293271469Skib			*where = (Elf_Addr)(obj->relocbase + rela->r_addend);
294271469Skib			break;
29538816Sdfr		/*
296271469Skib		 * missing:
297271469Skib		 * R_X86_64_GOTPCREL, R_X86_64_32, R_X86_64_32S, R_X86_64_16,
298271469Skib		 * R_X86_64_PC16, R_X86_64_8, R_X86_64_PC8
29938816Sdfr		 */
300271469Skib		default:
301271469Skib			_rtld_error("%s: Unsupported relocation type %u"
302271469Skib			    " in non-PLT relocations\n", obj->path,
303271469Skib			    (unsigned int)ELF_R_TYPE(rela->r_info));
30498100Sdillon			goto done;
30538816Sdfr		}
30638816Sdfr	}
30798103Sdillon	r = 0;
30898103Sdillondone:
309271469Skib	free(cache);
310233231Skib	return (r);
31138816Sdfr}
31238816Sdfr
31338816Sdfr/* Process the PLT relocations. */
31438816Sdfrint
31556780Sjdpreloc_plt(Obj_Entry *obj)
31638816Sdfr{
317115280Speter    const Elf_Rela *relalim;
318115280Speter    const Elf_Rela *rela;
31938816Sdfr
320115280Speter    relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize);
321115280Speter    for (rela = obj->pltrela;  rela < relalim;  rela++) {
32248205Sjdp	Elf_Addr *where;
32338816Sdfr
324228435Skib	switch(ELF_R_TYPE(rela->r_info)) {
325228435Skib	case R_X86_64_JMP_SLOT:
326228435Skib	  /* Relocate the GOT slot pointing into the PLT. */
327228435Skib	  where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
328228435Skib	  *where += (Elf_Addr)obj->relocbase;
329228435Skib	  break;
33038816Sdfr
331228435Skib	case R_X86_64_IRELATIVE:
332228435Skib	  obj->irelative = true;
333228435Skib	  break;
334228435Skib
335228435Skib	default:
336228435Skib	  _rtld_error("Unknown relocation type %x in PLT",
337228435Skib	    (unsigned int)ELF_R_TYPE(rela->r_info));
338228435Skib	  return (-1);
339228435Skib	}
34056780Sjdp    }
34156780Sjdp    return 0;
34256780Sjdp}
34338816Sdfr
34456780Sjdp/* Relocate the jump slots in an object. */
34556780Sjdpint
346233231Skibreloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
34756780Sjdp{
348115280Speter    const Elf_Rela *relalim;
349115280Speter    const Elf_Rela *rela;
35048205Sjdp
35156780Sjdp    if (obj->jmpslots_done)
35256780Sjdp	return 0;
353115280Speter    relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize);
354115280Speter    for (rela = obj->pltrela;  rela < relalim;  rela++) {
35585004Sdfr	Elf_Addr *where, target;
35656780Sjdp	const Elf_Sym *def;
35756780Sjdp	const Obj_Entry *defobj;
35856780Sjdp
359228435Skib	switch (ELF_R_TYPE(rela->r_info)) {
360228435Skib	case R_X86_64_JMP_SLOT:
361228435Skib	  where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
362233231Skib	  def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
363233231Skib		SYMLOOK_IN_PLT | flags, NULL, lockstate);
364228435Skib	  if (def == NULL)
365228435Skib	      return (-1);
366228435Skib	  if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
367228435Skib	      obj->gnu_ifunc = true;
368228435Skib	      continue;
369228435Skib	  }
370228435Skib	  target = (Elf_Addr)(defobj->relocbase + def->st_value + rela->r_addend);
371228435Skib	  reloc_jmpslot(where, target, defobj, obj, (const Elf_Rel *)rela);
372228435Skib	  break;
373228435Skib
374228435Skib	case R_X86_64_IRELATIVE:
375228435Skib	  break;
376228435Skib
377228435Skib	default:
378228435Skib	  _rtld_error("Unknown relocation type %x in PLT",
379228435Skib	    (unsigned int)ELF_R_TYPE(rela->r_info));
380228435Skib	  return (-1);
381228435Skib	}
38248205Sjdp    }
38356780Sjdp    obj->jmpslots_done = true;
38438816Sdfr    return 0;
38538816Sdfr}
386133063Sdfr
387228435Skibint
388228435Skibreloc_iresolve(Obj_Entry *obj, RtldLockState *lockstate)
389228435Skib{
390228435Skib    const Elf_Rela *relalim;
391228435Skib    const Elf_Rela *rela;
392228435Skib
393228503Skib    if (!obj->irelative)
394228503Skib	return (0);
395228435Skib    relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize);
396228435Skib    for (rela = obj->pltrela;  rela < relalim;  rela++) {
397228435Skib	Elf_Addr *where, target, *ptr;
398228435Skib
399228435Skib	switch (ELF_R_TYPE(rela->r_info)) {
400228435Skib	case R_X86_64_JMP_SLOT:
401228435Skib	  break;
402228435Skib
403228435Skib	case R_X86_64_IRELATIVE:
404228435Skib	  ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend);
405228435Skib	  where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
406228503Skib	  lock_release(rtld_bind_lock, lockstate);
407228435Skib	  target = ((Elf_Addr (*)(void))ptr)();
408228503Skib	  wlock_acquire(rtld_bind_lock, lockstate);
409228435Skib	  *where = target;
410228435Skib	  break;
411228435Skib	}
412228435Skib    }
413228503Skib    obj->irelative = false;
414228435Skib    return (0);
415228435Skib}
416228435Skib
417228435Skibint
418233231Skibreloc_gnu_ifunc(Obj_Entry *obj, int flags, RtldLockState *lockstate)
419228435Skib{
420228435Skib    const Elf_Rela *relalim;
421228435Skib    const Elf_Rela *rela;
422228435Skib
423228435Skib    if (!obj->gnu_ifunc)
424228435Skib	return (0);
425228435Skib    relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize);
426228435Skib    for (rela = obj->pltrela;  rela < relalim;  rela++) {
427228435Skib	Elf_Addr *where, target;
428228435Skib	const Elf_Sym *def;
429228435Skib	const Obj_Entry *defobj;
430228435Skib
431228435Skib	switch (ELF_R_TYPE(rela->r_info)) {
432228435Skib	case R_X86_64_JMP_SLOT:
433228435Skib	  where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
434233231Skib	  def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
435233231Skib		SYMLOOK_IN_PLT | flags, NULL, lockstate);
436228435Skib	  if (def == NULL)
437228435Skib	      return (-1);
438228435Skib	  if (ELF_ST_TYPE(def->st_info) != STT_GNU_IFUNC)
439228435Skib	      continue;
440228503Skib	  lock_release(rtld_bind_lock, lockstate);
441228435Skib	  target = (Elf_Addr)rtld_resolve_ifunc(defobj, def);
442228503Skib	  wlock_acquire(rtld_bind_lock, lockstate);
443228435Skib	  reloc_jmpslot(where, target, defobj, obj, (const Elf_Rel *)rela);
444228435Skib	  break;
445228435Skib	}
446228435Skib    }
447228435Skib    obj->gnu_ifunc = false;
448228503Skib    return (0);
449228435Skib}
450228435Skib
451133063Sdfrvoid
452133063Sdfrallocate_initial_tls(Obj_Entry *objs)
453133063Sdfr{
454133063Sdfr    /*
455133063Sdfr     * Fix the size of the static TLS block by using the maximum
456133063Sdfr     * offset allocated so far and adding a bit for dynamic modules to
457133063Sdfr     * use.
458133063Sdfr     */
459133063Sdfr    tls_static_space = tls_last_offset + RTLD_STATIC_TLS_EXTRA;
460133063Sdfr    amd64_set_fsbase(allocate_tls(objs, 0,
461157198Sdavidxu				  3*sizeof(Elf_Addr), sizeof(Elf_Addr)));
462133063Sdfr}
463133063Sdfr
464133063Sdfrvoid *__tls_get_addr(tls_index *ti)
465133063Sdfr{
466133063Sdfr    Elf_Addr** segbase;
467133063Sdfr
468133063Sdfr    __asm __volatile("movq %%fs:0, %0" : "=r" (segbase));
469133063Sdfr
470133063Sdfr    return tls_get_addr_common(&segbase[1], ti->ti_module, ti->ti_offset);
471133063Sdfr}
472