reloc.c revision 214194
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: head/libexec/rtld-elf/ia64/reloc.c 214194 2010-10-22 04:43:04Z marcel $
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/ia64_cpu.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
51extern Elf_Dyn _DYNAMIC;
52
53/*
54 * Macros for loading/storing unaligned 64-bit values.  These are
55 * needed because relocations can point to unaligned data.  This
56 * occurs in the DWARF2 exception frame tables generated by the
57 * compiler, for instance.
58 *
59 * We don't use these when relocating jump slots and GOT entries,
60 * since they are guaranteed to be aligned.
61 *
62 * XXX dfr stub for now.
63 */
64#define load64(p)	(*(u_int64_t *) (p))
65#define store64(p, v)	(*(u_int64_t *) (p) = (v))
66
67/* Allocate an @fptr. */
68
69#define FPTR_CHUNK_SIZE		64
70
71struct fptr_chunk {
72	struct fptr fptrs[FPTR_CHUNK_SIZE];
73};
74
75static struct fptr_chunk first_chunk;
76static struct fptr_chunk *current_chunk = &first_chunk;
77static struct fptr *next_fptr = &first_chunk.fptrs[0];
78static struct fptr *last_fptr = &first_chunk.fptrs[FPTR_CHUNK_SIZE];
79
80/*
81 * We use static storage initially so that we don't have to call
82 * malloc during init_rtld().
83 */
84static struct fptr *
85alloc_fptr(Elf_Addr target, Elf_Addr gp)
86{
87	struct fptr* fptr;
88
89	if (next_fptr == last_fptr) {
90		current_chunk = malloc(sizeof(struct fptr_chunk));
91		next_fptr = &current_chunk->fptrs[0];
92		last_fptr = &current_chunk->fptrs[FPTR_CHUNK_SIZE];
93	}
94	fptr = next_fptr;
95	next_fptr++;
96	fptr->target = target;
97	fptr->gp = gp;
98	return fptr;
99}
100
101static struct fptr **
102alloc_fptrs(Obj_Entry *obj, bool mapped)
103{
104	struct fptr **fptrs;
105	size_t fbytes;
106
107	fbytes = obj->nchains * sizeof(struct fptr *);
108
109	/*
110	 * Avoid malloc, if requested. Happens when relocating
111	 * rtld itself on startup.
112	 */
113	if (mapped) {
114		fptrs = mmap(NULL, fbytes, PROT_READ|PROT_WRITE,
115	    	    MAP_ANON, -1, 0);
116		if (fptrs == MAP_FAILED)
117			fptrs = NULL;
118	} else {
119		fptrs = malloc(fbytes);
120		if (fptrs != NULL)
121 			memset(fptrs, 0, fbytes);
122	}
123
124	/*
125	 * This assertion is necessary to guarantee function pointer
126	 * uniqueness
127 	 */
128	assert(fptrs != NULL);
129
130	return (obj->priv = fptrs);
131}
132
133static void
134free_fptrs(Obj_Entry *obj, bool mapped)
135{
136	struct fptr **fptrs;
137	size_t fbytes;
138
139	fptrs  = obj->priv;
140	if (fptrs == NULL)
141		return;
142
143	fbytes = obj->nchains * sizeof(struct fptr *);
144	if (mapped)
145		munmap(fptrs, fbytes);
146	else
147		free(fptrs);
148	obj->priv = NULL;
149}
150
151/* Relocate a non-PLT object with addend. */
152static int
153reloc_non_plt_obj(Obj_Entry *obj_rtld, Obj_Entry *obj, const Elf_Rela *rela,
154		  SymCache *cache)
155{
156	struct fptr **fptrs;
157	Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
158
159	switch (ELF_R_TYPE(rela->r_info)) {
160	case R_IA_64_REL64LSB:
161		/*
162		 * We handle rtld's relocations in rtld_start.S
163		 */
164		if (obj != obj_rtld)
165			store64(where,
166				load64(where) + (Elf_Addr) obj->relocbase);
167		break;
168
169	case R_IA_64_DIR64LSB: {
170		const Elf_Sym *def;
171		const Obj_Entry *defobj;
172		Elf_Addr target;
173
174		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
175				  false, cache);
176		if (def == NULL)
177			return -1;
178
179		target = (def->st_shndx != SHN_UNDEF)
180		    ? (Elf_Addr)(defobj->relocbase + def->st_value) : 0;
181		store64(where, target + rela->r_addend);
182		break;
183	}
184
185	case R_IA_64_FPTR64LSB: {
186		/*
187		 * We have to make sure that all @fptr references to
188		 * the same function are identical so that code can
189		 * compare function pointers.
190		 */
191		const Elf_Sym *def;
192		const Obj_Entry *defobj;
193		struct fptr *fptr = 0;
194		Elf_Addr target, gp;
195		int sym_index;
196
197		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
198				  true, cache);
199		if (def == NULL) {
200			/*
201			 * XXX r_debug_state is problematic and find_symdef()
202			 * returns NULL for it. This probably has something to
203			 * do with symbol versioning (r_debug_state is in the
204			 * symbol map). If we return -1 in that case we abort
205			 * relocating rtld, which typically is fatal. So, for
206			 * now just skip the symbol when we're relocating
207			 * rtld. We don't care about r_debug_state unless we
208			 * are being debugged.
209			 */
210			if (obj != obj_rtld)
211				return -1;
212			break;
213		}
214
215		if (def->st_shndx != SHN_UNDEF) {
216			target = (Elf_Addr)(defobj->relocbase + def->st_value);
217			gp = (Elf_Addr)defobj->pltgot;
218
219			/* rtld is allowed to reference itself only */
220			assert(!obj->rtld || obj == defobj);
221			fptrs = defobj->priv;
222			if (fptrs == NULL)
223				fptrs = alloc_fptrs((Obj_Entry *) defobj,
224				    obj->rtld);
225
226			sym_index = def - defobj->symtab;
227
228			/*
229			 * Find the @fptr, using fptrs as a helper.
230			 */
231			if (fptrs)
232				fptr = fptrs[sym_index];
233			if (!fptr) {
234				fptr = alloc_fptr(target, gp);
235				if (fptrs)
236					fptrs[sym_index] = fptr;
237			}
238		} else
239			fptr = NULL;
240
241		store64(where, (Elf_Addr)fptr);
242		break;
243	}
244
245	case R_IA_64_IPLTLSB: {
246		/*
247		 * Relocation typically used to populate C++ virtual function
248		 * tables. It creates a 128-bit function descriptor at the
249		 * specified memory address.
250		 */
251		const Elf_Sym *def;
252		const Obj_Entry *defobj;
253		struct fptr *fptr;
254		Elf_Addr target, gp;
255
256		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
257				  false, cache);
258		if (def == NULL)
259			return -1;
260
261		if (def->st_shndx != SHN_UNDEF) {
262			target = (Elf_Addr)(defobj->relocbase + def->st_value);
263			gp = (Elf_Addr)defobj->pltgot;
264		} else {
265			target = 0;
266			gp = 0;
267		}
268
269		fptr = (void*)where;
270		store64(&fptr->target, target);
271		store64(&fptr->gp, gp);
272		break;
273	}
274
275	case R_IA_64_DTPMOD64LSB: {
276		const Elf_Sym *def;
277		const Obj_Entry *defobj;
278
279		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
280				  false, cache);
281		if (def == NULL)
282			return -1;
283
284		store64(where, defobj->tlsindex);
285		break;
286	}
287
288	case R_IA_64_DTPREL64LSB: {
289		const Elf_Sym *def;
290		const Obj_Entry *defobj;
291
292		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
293				  false, cache);
294		if (def == NULL)
295			return -1;
296
297		store64(where, def->st_value + rela->r_addend);
298		break;
299	}
300
301	case R_IA_64_TPREL64LSB: {
302		const Elf_Sym *def;
303		const Obj_Entry *defobj;
304
305		def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
306				  false, cache);
307		if (def == NULL)
308			return -1;
309
310		/*
311		 * We lazily allocate offsets for static TLS as we
312		 * see the first relocation that references the
313		 * TLS block. This allows us to support (small
314		 * amounts of) static TLS in dynamically loaded
315		 * modules. If we run out of space, we generate an
316		 * error.
317		 */
318		if (!defobj->tls_done) {
319			if (!allocate_tls_offset((Obj_Entry*) defobj)) {
320				_rtld_error("%s: No space available for static "
321				    "Thread Local Storage", obj->path);
322				return -1;
323			}
324		}
325
326		store64(where, defobj->tlsoffset + def->st_value + rela->r_addend);
327		break;
328	}
329
330	case R_IA_64_NONE:
331		break;
332
333	default:
334		_rtld_error("%s: Unsupported relocation type %u"
335			    " in non-PLT relocations\n", obj->path,
336			    (unsigned int)ELF_R_TYPE(rela->r_info));
337		return -1;
338	}
339
340	return(0);
341}
342
343/* Process the non-PLT relocations. */
344int
345reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld)
346{
347	const Elf_Rel *rellim;
348	const Elf_Rel *rel;
349	const Elf_Rela *relalim;
350	const Elf_Rela *rela;
351	SymCache *cache;
352	int bytes = obj->nchains * sizeof(SymCache);
353	int r = -1;
354
355	/*
356	 * The dynamic loader may be called from a thread, we have
357	 * limited amounts of stack available so we cannot use alloca().
358	 */
359	cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0);
360	if (cache == MAP_FAILED)
361		cache = NULL;
362
363	/* Perform relocations without addend if there are any: */
364	rellim = (const Elf_Rel *) ((caddr_t) obj->rel + obj->relsize);
365	for (rel = obj->rel;  obj->rel != NULL && rel < rellim;  rel++) {
366		Elf_Rela locrela;
367
368		locrela.r_info = rel->r_info;
369		locrela.r_offset = rel->r_offset;
370		locrela.r_addend = 0;
371		if (reloc_non_plt_obj(obj_rtld, obj, &locrela, cache))
372			goto done;
373	}
374
375	/* Perform relocations with addend if there are any: */
376	relalim = (const Elf_Rela *) ((caddr_t) obj->rela + obj->relasize);
377	for (rela = obj->rela;  obj->rela != NULL && rela < relalim;  rela++) {
378		if (reloc_non_plt_obj(obj_rtld, obj, rela, cache))
379			goto done;
380	}
381
382	r = 0;
383done:
384	if (cache)
385		munmap(cache, bytes);
386
387	/*
388	 * Release temporarily mapped fptrs if relocating
389	 * rtld object itself. A new table will be created
390	 * in make_function_pointer using malloc when needed.
391	 */
392	if (obj->rtld && obj->priv)
393		free_fptrs(obj, true);
394
395	return (r);
396}
397
398/* Process the PLT relocations. */
399int
400reloc_plt(Obj_Entry *obj)
401{
402	/* All PLT relocations are the same kind: Elf_Rel or Elf_Rela. */
403	if (obj->pltrelsize != 0) {
404		const Elf_Rel *rellim;
405		const Elf_Rel *rel;
406
407		rellim = (const Elf_Rel *)
408			((char *)obj->pltrel + obj->pltrelsize);
409		for (rel = obj->pltrel;  rel < rellim;  rel++) {
410			Elf_Addr *where;
411
412			assert(ELF_R_TYPE(rel->r_info) == R_IA_64_IPLTLSB);
413
414			/* Relocate the @fptr pointing into the PLT. */
415			where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
416			*where += (Elf_Addr)obj->relocbase;
417		}
418	} else {
419		const Elf_Rela *relalim;
420		const Elf_Rela *rela;
421
422		relalim = (const Elf_Rela *)
423			((char *)obj->pltrela + obj->pltrelasize);
424		for (rela = obj->pltrela;  rela < relalim;  rela++) {
425			Elf_Addr *where;
426
427			assert(ELF_R_TYPE(rela->r_info) == R_IA_64_IPLTLSB);
428
429			/* Relocate the @fptr pointing into the PLT. */
430			where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
431			*where += (Elf_Addr)obj->relocbase;
432		}
433	}
434	return 0;
435}
436
437/* Relocate the jump slots in an object. */
438int
439reloc_jmpslots(Obj_Entry *obj)
440{
441	if (obj->jmpslots_done)
442		return 0;
443	/* All PLT relocations are the same kind: Elf_Rel or Elf_Rela. */
444	if (obj->pltrelsize != 0) {
445		const Elf_Rel *rellim;
446		const Elf_Rel *rel;
447
448		rellim = (const Elf_Rel *)
449			((char *)obj->pltrel + obj->pltrelsize);
450		for (rel = obj->pltrel;  rel < rellim;  rel++) {
451			Elf_Addr *where;
452			const Elf_Sym *def;
453			const Obj_Entry *defobj;
454
455			assert(ELF_R_TYPE(rel->r_info) == R_IA_64_IPLTLSB);
456			where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
457			def = find_symdef(ELF_R_SYM(rel->r_info), obj,
458					  &defobj, true, NULL);
459			if (def == NULL)
460				return -1;
461			reloc_jmpslot(where,
462				      (Elf_Addr)(defobj->relocbase
463						 + def->st_value),
464				      defobj, obj, rel);
465		}
466	} else {
467		const Elf_Rela *relalim;
468		const Elf_Rela *rela;
469
470		relalim = (const Elf_Rela *)
471			((char *)obj->pltrela + obj->pltrelasize);
472		for (rela = obj->pltrela;  rela < relalim;  rela++) {
473			Elf_Addr *where;
474			const Elf_Sym *def;
475			const Obj_Entry *defobj;
476
477			where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
478			def = find_symdef(ELF_R_SYM(rela->r_info), obj,
479					  &defobj, true, NULL);
480			if (def == NULL)
481				return -1;
482			reloc_jmpslot(where,
483				      (Elf_Addr)(defobj->relocbase
484						 + def->st_value),
485				      defobj, obj, (Elf_Rel *)rela);
486		}
487	}
488	obj->jmpslots_done = true;
489	return 0;
490}
491
492/* Fixup the jump slot at "where" to transfer control to "target". */
493Elf_Addr
494reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const Obj_Entry *obj,
495	      const Obj_Entry *refobj, const Elf_Rel *rel)
496{
497	Elf_Addr stubaddr;
498
499	dbg(" reloc_jmpslot: where=%p, target=%p, gp=%p",
500	    (void *)where, (void *)target, (void *)obj->pltgot);
501	stubaddr = *where;
502	if (stubaddr != target) {
503
504		/*
505		 * Point this @fptr directly at the target. Update the
506		 * gp value first so that we don't break another cpu
507		 * which is currently executing the PLT entry.
508		 */
509		where[1] = (Elf_Addr) obj->pltgot;
510		ia64_mf();
511		where[0] = target;
512		ia64_mf();
513	}
514
515	/*
516	 * The caller needs an @fptr for the adjusted entry. The PLT
517	 * entry serves this purpose nicely.
518	 */
519	return (Elf_Addr) where;
520}
521
522/*
523 * XXX ia64 doesn't seem to have copy relocations.
524 *
525 * Returns 0 on success, -1 on failure.
526 */
527int
528do_copy_relocations(Obj_Entry *dstobj)
529{
530
531	return 0;
532}
533
534/*
535 * Return the @fptr representing a given function symbol.
536 */
537void *
538make_function_pointer(const Elf_Sym *sym, const Obj_Entry *obj)
539{
540	struct fptr **fptrs = obj->priv;
541	int index = sym - obj->symtab;
542
543	if (!fptrs) {
544		/*
545		 * This should only happen for something like
546		 * dlsym("dlopen"). Actually, I'm not sure it can ever
547		 * happen.
548		 */
549		fptrs = alloc_fptrs((Obj_Entry *) obj, false);
550	}
551	if (!fptrs[index]) {
552		Elf_Addr target, gp;
553		target = (Elf_Addr) (obj->relocbase + sym->st_value);
554		gp = (Elf_Addr) obj->pltgot;
555		fptrs[index] = alloc_fptr(target, gp);
556	}
557	return fptrs[index];
558}
559
560void
561call_initfini_pointer(const Obj_Entry *obj, Elf_Addr target)
562{
563	struct fptr fptr;
564
565	fptr.gp = (Elf_Addr) obj->pltgot;
566	fptr.target = target;
567	dbg(" initfini: target=%p, gp=%p",
568	    (void *) fptr.target, (void *) fptr.gp);
569	((InitFunc) &fptr)();
570}
571
572/* Initialize the special PLT entries. */
573void
574init_pltgot(Obj_Entry *obj)
575{
576	const Elf_Dyn *dynp;
577	Elf_Addr *pltres = 0;
578
579	/*
580	 * When there are no PLT relocations, the DT_IA_64_PLT_RESERVE entry
581	 * is bogus. Do not setup the BOR pointers in that case. An example
582	 * of where this happens is /usr/lib/libxpg4.so.3.
583	 */
584	if (obj->pltrelasize == 0 && obj->pltrelsize == 0)
585		return;
586
587	/*
588	 * Find the PLT RESERVE section.
589	 */
590	for (dynp = obj->dynamic;  dynp->d_tag != DT_NULL;  dynp++) {
591		if (dynp->d_tag == DT_IA_64_PLT_RESERVE)
592			pltres = (u_int64_t *)
593				(obj->relocbase + dynp->d_un.d_ptr);
594	}
595	if (!pltres)
596		errx(1, "Can't find DT_IA_64_PLT_RESERVE entry");
597
598	/*
599	 * The PLT RESERVE section is used to get values to pass to
600	 * _rtld_bind when lazy binding.
601	 */
602	pltres[0] = (Elf_Addr) obj;
603	pltres[1] = FPTR_TARGET(_rtld_bind_start);
604	pltres[2] = FPTR_GP(_rtld_bind_start);
605}
606
607void
608allocate_initial_tls(Obj_Entry *list)
609{
610    void *tpval;
611
612    /*
613     * Fix the size of the static TLS block by using the maximum
614     * offset allocated so far and adding a bit for dynamic modules to
615     * use.
616     */
617    tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA;
618
619    tpval = allocate_tls(list, NULL, TLS_TCB_SIZE, 16);
620    __asm __volatile("mov r13 = %0" :: "r"(tpval));
621}
622
623void *__tls_get_addr(unsigned long module, unsigned long offset)
624{
625    register Elf_Addr** tp __asm__("r13");
626
627    return tls_get_addr_common(tp, module, offset);
628}
629