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