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