Annotation of src/libexec/ld.elf_so/reloc.c, Revision 1.16
1.16 ! christos 1: /* $NetBSD: reloc.c,v 1.15 1999/02/27 21:38:04 scottr Exp $ */
1.1 cgd 2:
3: /*
4: * Copyright 1996 John D. Polstra.
5: * Copyright 1996 Matt Thomas <matt@3am-software.com>
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by John Polstra.
19: * 4. The name of the author may not be used to endorse or promote products
20: * derived from this software without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32: */
33:
34: /*
35: * Dynamic linker for ELF.
36: *
37: * John Polstra <jdp@polstra.com>.
38: */
39:
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: #include <sys/types.h>
49: #include <sys/mman.h>
50: #include <dirent.h>
51:
52: #include "debug.h"
53: #include "rtld.h"
54:
1.14 pk 55: #ifndef RTLD_INHIBIT_COPY_RELOCS
1.16 ! christos 56: static int _rtld_do_copy_relocation __P((const Obj_Entry *, const Elf_RelA *,
! 57: bool));
! 58:
1.4 christos 59: /*
60: * XXX: These don't work for the alpha and i386; don't know about powerpc
61: * The alpha and the i386 avoid the problem by compiling everything PIC.
62: * These relocation are supposed to be writing the address of the
63: * function to be called on the bss.rel or bss.rela segment, but:
64: * - st_size == 0
65: * - on the i386 at least the call instruction is a direct call
66: * not an indirect call.
67: */
1.1 cgd 68: static int
1.16 ! christos 69: _rtld_do_copy_relocation(dstobj, rela, dodebug)
! 70: const Obj_Entry *dstobj;
! 71: const Elf_RelA *rela;
! 72: bool dodebug;
1.1 cgd 73: {
1.11 christos 74: void *dstaddr = (void *)(dstobj->relocbase + rela->r_offset);
75: const Elf_Sym *dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info);
76: const char *name = dstobj->strtab + dstsym->st_name;
77: unsigned long hash = _rtld_elf_hash(name);
78: size_t size = dstsym->st_size;
79: const void *srcaddr;
80: const Elf_Sym *srcsym;
81: Obj_Entry *srcobj;
82:
83: for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next)
84: if ((srcsym = _rtld_symlook_obj(name, hash, srcobj,
85: false)) != NULL)
86: break;
87:
88: if (srcobj == NULL) {
89: _rtld_error("Undefined symbol \"%s\" referenced from COPY"
90: " relocation in %s", name, dstobj->path);
1.14 pk 91: return (-1);
1.11 christos 92: }
93: srcaddr = (const void *)(srcobj->relocbase + srcsym->st_value);
94: (void)memcpy(dstaddr, srcaddr, size);
1.16 ! christos 95: rdbg(dodebug, ("COPY %s %s %s --> src=%p dst=%p *dst= %p size %d",
1.11 christos 96: dstobj->path, srcobj->path, name, (void *)srcaddr,
1.16 ! christos 97: (void *)dstaddr, (void *)*(long *)dstaddr, size));
1.14 pk 98: return (0);
1.1 cgd 99: }
1.14 pk 100: #endif /* RTLD_INHIBIT_COPY_RELOCS */
1.11 christos 101:
102:
1.1 cgd 103: /*
104: * Process the special R_xxx_COPY relocations in the main program. These
105: * copy data from a shared object into a region in the main program's BSS
106: * segment.
107: *
108: * Returns 0 on success, -1 on failure.
109: */
110: int
1.16 ! christos 111: _rtld_do_copy_relocations(dstobj, dodebug)
! 112: const Obj_Entry *dstobj;
! 113: bool dodebug;
1.1 cgd 114: {
1.14 pk 115: #ifndef RTLD_INHIBIT_COPY_RELOCS
116:
117: /* COPY relocations are invalid elsewhere */
118: assert(dstobj->mainprog);
1.1 cgd 119:
1.11 christos 120: if (dstobj->rel != NULL) {
121: const Elf_Rel *rel;
122: for (rel = dstobj->rel; rel < dstobj->rellim; ++rel) {
123: if (ELF_R_TYPE(rel->r_info) == R_TYPE(COPY)) {
124: Elf_RelA ourrela;
125: ourrela.r_info = rel->r_info;
126: ourrela.r_offset = rel->r_offset;
127: ourrela.r_addend = 0;
128: if (_rtld_do_copy_relocation(dstobj,
129: &ourrela, dodebug) < 0)
1.14 pk 130: return (-1);
1.11 christos 131: }
132: }
133: }
134: if (dstobj->rela != NULL) {
135: const Elf_RelA *rela;
136: for (rela = dstobj->rela; rela < dstobj->relalim; ++rela) {
137: if (ELF_R_TYPE(rela->r_info) == R_TYPE(COPY)) {
138: if (_rtld_do_copy_relocation(dstobj, rela,
139: dodebug) < 0)
1.14 pk 140: return (-1);
1.11 christos 141: }
142: }
1.1 cgd 143: }
1.14 pk 144: #endif /* RTLD_INHIBIT_COPY_RELOCS */
1.1 cgd 145:
1.14 pk 146: return (0);
1.1 cgd 147: }
1.9 pk 148:
149:
1.11 christos 150: #ifndef __sparc__
151: int
1.16 ! christos 152: _rtld_relocate_nonplt_object(obj, rela, dodebug)
! 153: const Obj_Entry *obj;
! 154: const Elf_RelA *rela;
! 155: bool dodebug;
1.9 pk 156: {
1.11 christos 157: Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
158: const Elf_Sym *def;
1.9 pk 159: const Obj_Entry *defobj;
1.15 scottr 160: #if defined(__i386__) || defined(__alpha__)
1.11 christos 161: extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
162: extern Elf_Dyn _DYNAMIC;
1.15 scottr 163: #endif
1.11 christos 164: Elf_Addr tmp;
1.9 pk 165:
1.11 christos 166: switch (ELF_R_TYPE(rela->r_info)) {
1.9 pk 167:
1.11 christos 168: case R_TYPE(NONE):
169: break;
1.9 pk 170:
1.11 christos 171: #ifdef __i386__
172: case R_TYPE(GOT32):
1.9 pk 173:
1.11 christos 174: def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj,
175: &defobj, false);
176: if (def == NULL)
177: return -1;
1.9 pk 178:
1.11 christos 179: tmp = (Elf_Addr)(defobj->relocbase + def->st_value);
180: if (*where != tmp)
181: *where = tmp;
1.16 ! christos 182: rdbg(dodebug, ("GOT32 %s in %s --> %p in %s",
1.11 christos 183: defobj->strtab + def->st_name, obj->path,
1.16 ! christos 184: (void *)*where, defobj->path));
1.11 christos 185: break;
1.9 pk 186:
1.11 christos 187: case R_TYPE(PC32):
188: /*
189: * I don't think the dynamic linker should ever see this
190: * type of relocation. But the binutils-2.6 tools sometimes
191: * generate it.
192: */
1.9 pk 193:
1.11 christos 194: def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj,
195: &defobj, false);
196: if (def == NULL)
197: return -1;
1.9 pk 198:
1.11 christos 199: *where += (Elf_Addr)(defobj->relocbase + def->st_value) -
200: (Elf_Addr)where;
1.16 ! christos 201: rdbg(dodebug, ("PC32 %s in %s --> %p in %s",
1.11 christos 202: defobj->strtab + def->st_name, obj->path,
1.16 ! christos 203: (void *)*where, defobj->path));
1.11 christos 204: break;
205:
206: case R_TYPE(32):
207: def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj,
208: &defobj, false);
209: if (def == NULL)
210: return -1;
1.9 pk 211:
1.11 christos 212: *where += (Elf_Addr)(defobj->relocbase + def->st_value);
1.16 ! christos 213: rdbg(dodebug, ("32 %s in %s --> %p in %s",
1.11 christos 214: defobj->strtab + def->st_name, obj->path,
1.16 ! christos 215: (void *)*where, defobj->path));
1.11 christos 216: break;
1.4 christos 217: #endif /* __i386__ */
218:
1.1 cgd 219: #ifdef __alpha__
1.11 christos 220: case R_TYPE(REFQUAD):
221: def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj,
222: &defobj, false);
223: if (def == NULL)
224: return -1;
1.1 cgd 225:
1.11 christos 226: tmp = (Elf_Addr)(defobj->relocbase + def->st_value) +
227: *where + rela->r_addend;
1.12 tv 228: if (*where != tmp)
229: *where = tmp;
1.16 ! christos 230: rdbg(dodebug, ("REFQUAD %s in %s --> %p in %s",
1.11 christos 231: defobj->strtab + def->st_name, obj->path,
1.16 ! christos 232: (void *)*where, defobj->path));
1.11 christos 233: break;
1.4 christos 234: #endif /* __alpha__ */
1.1 cgd 235:
1.4 christos 236: #if defined(__i386__) || defined(__alpha__)
1.11 christos 237: case R_TYPE(GLOB_DAT):
238: def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj,
239: &defobj, false);
240: if (def == NULL)
241: return -1;
1.1 cgd 242:
1.11 christos 243: if (*where != (Elf_Addr)(defobj->relocbase + def->st_value))
244: *where = (Elf_Addr)(defobj->relocbase + def->st_value);
1.16 ! christos 245: rdbg(dodebug, ("GLOB_DAT %s in %s --> %p in %s",
1.11 christos 246: defobj->strtab + def->st_name, obj->path,
1.16 ! christos 247: (void *)*where, defobj->path));
1.11 christos 248: break;
249:
250: case R_TYPE(RELATIVE):
1.12 tv 251: if ((caddr_t)where < (caddr_t)_GLOBAL_OFFSET_TABLE_ ||
1.11 christos 252: (caddr_t)where >= (caddr_t)&_DYNAMIC) {
253: *where += (Elf_Addr)obj->relocbase;
1.16 ! christos 254: rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path,
! 255: (void *)*where));
1.11 christos 256: }
257: else
1.16 ! christos 258: rdbg(dodebug, ("RELATIVE in %s stays at %p",
! 259: obj->path, (void *)*where));
1.11 christos 260: break;
1.1 cgd 261:
1.11 christos 262: case R_TYPE(COPY):
263: /*
264: * These are deferred until all other relocations have
265: * been done. All we do here is make sure that the COPY
266: * relocation is not in a shared library. They are allowed
267: * only in executable files.
268: */
269: if (!obj->mainprog) {
270: _rtld_error(
271: "%s: Unexpected R_COPY relocation in shared library",
272: obj->path);
273: return -1;
274: }
1.16 ! christos 275: rdbg(dodebug, ("COPY (avoid in main)"));
1.11 christos 276: break;
1.4 christos 277: #endif /* __i386__ || __alpha__ */
1.2 mhitch 278:
279: #ifdef __mips__
1.11 christos 280: case R_TYPE(REL32):
281: /* 32-bit PC-relative reference */
282: def = obj->symtab + ELF_R_SYM(rela->r_info);
283:
284: if (ELF_SYM_BIND(def->st_info) == Elf_estb_local &&
285: (ELF_SYM_TYPE(def->st_info) == Elf_estt_section ||
286: ELF_SYM_TYPE(def->st_info) == Elf_estt_notype)) {
287: *where += (Elf_Addr)obj->relocbase;
1.16 ! christos 288: rdbg(dodebug, ("REL32 in %s --> %p", obj->path,
! 289: (void *)*where));
1.11 christos 290: } else {
291: /* XXX maybe do something re: bootstrapping? */
292: def = _rtld_find_symdef(_rtld_objlist, rela->r_info,
293: NULL, obj, &defobj, false);
294: if (def == NULL)
295: return -1;
296: *where += (Elf_Addr)(defobj->relocbase + def->st_value);
1.16 ! christos 297: rdbg(dodebug, ("REL32 %s in %s --> %p in %s",
1.11 christos 298: defobj->strtab + def->st_name, obj->path,
1.16 ! christos 299: (void *)*where, defobj->path));
1.11 christos 300: }
301: break;
1.2 mhitch 302:
1.11 christos 303: #endif /* __mips__ */
1.1 cgd 304:
1.3 tsubai 305: #ifdef __powerpc__
1.11 christos 306: case R_TYPE(32): /* word32 S + A */
307: case R_TYPE(GLOB_DAT): /* word32 S + A */
308: def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj,
309: &defobj, false);
310: if (def == NULL)
311: return -1;
1.3 tsubai 312:
1.11 christos 313: tmp = (Elf_Addr)(defobj->relocbase + def->st_value +
314: rela->r_addend);
1.3 tsubai 315:
1.11 christos 316: if (*where != tmp)
317: *where = tmp;
1.16 ! christos 318: rdbg(dodebug, ("32/GLOB_DAT %s in %s --> %p in %s",
1.11 christos 319: defobj->strtab + def->st_name, obj->path,
1.16 ! christos 320: (void *)*where, defobj->path));
1.11 christos 321: break;
322:
323: case R_TYPE(COPY):
1.16 ! christos 324: rdbg(dodebug, ("COPY"));
1.11 christos 325: break;
326:
327: case R_TYPE(JMP_SLOT):
1.16 ! christos 328: rdbg(dodebug, ("JMP_SLOT"));
1.11 christos 329: break;
330:
331: case R_TYPE(RELATIVE): /* word32 B + A */
332: tmp = (Elf_Addr)(obj->relocbase + rela->r_addend);
1.15 scottr 333: if (obj == &_rtld_objself && *where == tmp)
1.11 christos 334: break; /* GOT - already done */
335:
336: *where = tmp;
1.16 ! christos 337: rdbg(dodebug, ("RELATIVE in %s --> %p", obj->path,
! 338: (void *)*where));
1.11 christos 339: break;
1.4 christos 340: #endif /* __powerpc__ */
1.3 tsubai 341:
1.11 christos 342: default:
343: def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj,
344: &defobj, true);
1.16 ! christos 345: rdbg(dodebug, ("sym = %lu, type = %lu, offset = %p, "
1.11 christos 346: "addend = %p, contents = %p, symbol = %s",
347: (u_long)ELF_R_SYM(rela->r_info),
348: (u_long)ELF_R_TYPE(rela->r_info),
349: (void *)rela->r_offset, (void *)rela->r_addend,
350: (void *)*where,
1.16 ! christos 351: def ? defobj->strtab + def->st_name : "??"));
1.11 christos 352: _rtld_error("%s: Unsupported relocation type %d"
353: "in non-PLT relocations\n",
354: obj->path, ELF_R_TYPE(rela->r_info));
355: return -1;
356: }
357: return 0;
1.1 cgd 358: }
1.9 pk 359:
360:
361:
1.11 christos 362: int
1.16 ! christos 363: _rtld_relocate_plt_object(obj, rela, addrp, bind_now, dodebug)
! 364: const Obj_Entry *obj;
! 365: const Elf_RelA *rela;
! 366: caddr_t *addrp;
! 367: bool bind_now;
! 368: bool dodebug;
1.1 cgd 369: {
1.16 ! christos 370: Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
! 371: Elf_Addr new_value;
1.1 cgd 372:
1.11 christos 373: /* Fully resolve procedure addresses now */
1.2 mhitch 374:
1.3 tsubai 375: #if defined(__powerpc__)
1.11 christos 376: return _rtld_reloc_powerpc_plt(obj, rela, bind_now);
1.3 tsubai 377: #endif
378:
1.11 christos 379: #if defined(__alpha__) || defined(__i386__)
380: if (bind_now || obj->pltgot == NULL) {
381: const Elf_Sym *def;
382: const Obj_Entry *defobj;
383:
384: assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT));
1.1 cgd 385:
1.11 christos 386: def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj,
387: &defobj, true);
388: if (def == NULL)
389: return -1;
1.1 cgd 390:
1.11 christos 391: new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
1.16 ! christos 392: rdbg(dodebug, ("bind now %d/fixup in %s --> old=%p new=%p",
1.11 christos 393: (int)bind_now,
394: defobj->strtab + def->st_name,
1.16 ! christos 395: (void *)*where, (void *)new_value));
1.11 christos 396: } else
397: #endif /* __alpha__ || __i386__ */
398: if (!obj->mainprog) {
399: /* Just relocate the GOT slots pointing into the PLT */
400: new_value = *where + (Elf_Addr)(obj->relocbase);
1.16 ! christos 401: rdbg(dodebug, ("fixup !main in %s --> %p", obj->path,
! 402: (void *)*where));
1.11 christos 403: } else {
404: return 0;
405: }
406: /*
407: * Since this page is probably copy-on-write, let's not write
408: * it unless we really really have to.
409: */
410: if (*where != new_value)
411: *where = new_value;
412: if (addrp != NULL)
413: *addrp = *(caddr_t *)(obj->relocbase + rela->r_offset);
1.7 tv 414: return 0;
1.1 cgd 415: }
1.11 christos 416: #endif /* __sparc__ */
1.9 pk 417:
1.1 cgd 418: caddr_t
1.16 ! christos 419: _rtld_bind(obj, reloff)
! 420: const Obj_Entry *obj;
! 421: Elf_Word reloff;
1.1 cgd 422: {
1.11 christos 423: const Elf_RelA *rela;
424: Elf_RelA ourrela;
425: caddr_t addr;
1.1 cgd 426:
1.11 christos 427: if (obj->pltrel != NULL) {
428: const Elf_Rel *rel;
1.1 cgd 429:
1.11 christos 430: rel = (const Elf_Rel *)((caddr_t) obj->pltrel + reloff);
431: ourrela.r_info = rel->r_info;
432: ourrela.r_offset = rel->r_offset;
433: rela = &ourrela;
434: } else {
435: rela = (const Elf_RelA *)((caddr_t) obj->pltrela + reloff);
436: }
437:
438: if (_rtld_relocate_plt_object(obj, rela, &addr, true, true) < 0)
439: _rtld_die();
1.1 cgd 440:
1.11 christos 441: return addr;
1.1 cgd 442: }
1.9 pk 443:
1.1 cgd 444: /*
445: * Relocate newly-loaded shared objects. The argument is a pointer to
446: * the Obj_Entry for the first such object. All objects from the first
447: * to the end of the list of objects are relocated. Returns 0 on success,
448: * or -1 on failure.
449: */
450: int
1.16 ! christos 451: _rtld_relocate_objects(first, bind_now, dodebug)
! 452: Obj_Entry *first;
! 453: bool bind_now;
! 454: bool dodebug;
1.1 cgd 455: {
1.16 ! christos 456: Obj_Entry *obj;
! 457: int ok = 1;
1.1 cgd 458:
1.11 christos 459: for (obj = first; obj != NULL; obj = obj->next) {
1.16 ! christos 460: if (obj->nbuckets == 0 || obj->nchains == 0 ||
! 461: obj->buckets == NULL || obj->symtab == NULL ||
! 462: obj->strtab == NULL) {
1.11 christos 463: _rtld_error("%s: Shared object has no run-time"
464: " symbol table", obj->path);
465: return -1;
466: }
1.16 ! christos 467: rdbg(dodebug, (" relocating %s (%ld/%ld rel/rela, "
1.11 christos 468: "%ld/%ld plt rel/rela)",
469: obj->path,
470: (long)(obj->rellim - obj->rel),
471: (long)(obj->relalim - obj->rela),
472: (long)(obj->pltrellim - obj->pltrel),
1.16 ! christos 473: (long)(obj->pltrelalim - obj->pltrela)));
1.11 christos 474:
475: if (obj->textrel) {
476: /*
477: * There are relocations to the write-protected text
478: * segment.
479: */
480: if (mprotect(obj->mapbase, obj->textsize,
481: PROT_READ | PROT_WRITE | PROT_EXEC) == -1) {
482: _rtld_error("%s: Cannot write-enable text "
483: "segment: %s", obj->path, xstrerror(errno));
484: return -1;
485: }
486: }
487: if (obj->rel != NULL) {
488: /* Process the non-PLT relocations. */
489: const Elf_Rel *rel;
490: for (rel = obj->rel; rel < obj->rellim; ++rel) {
491: Elf_RelA ourrela;
492: ourrela.r_info = rel->r_info;
493: ourrela.r_offset = rel->r_offset;
1.2 mhitch 494: #if defined(__mips__)
1.11 christos 495: /* rel->r_offset is not valid on mips? */
496: if (ELF_R_TYPE(ourrela.r_info) == R_TYPE(NONE))
497: ourrela.r_addend = 0;
498: else
499: #endif
500: ourrela.r_addend =
501: *(Elf_Word *)(obj->relocbase +
502: rel->r_offset);
503:
504: if (_rtld_relocate_nonplt_object(obj, &ourrela,
505: dodebug) < 0)
506: ok = 0;
507: }
508: }
509: if (obj->rela != NULL) {
510: /* Process the non-PLT relocations. */
511: const Elf_RelA *rela;
512: for (rela = obj->rela; rela < obj->relalim; ++rela) {
513: if (_rtld_relocate_nonplt_object(obj, rela,
514: dodebug) < 0)
515: ok = 0;
516: }
517: }
518: if (obj->textrel) { /* Re-protected the text segment. */
519: if (mprotect(obj->mapbase, obj->textsize,
520: PROT_READ | PROT_EXEC) == -1) {
521: _rtld_error("%s: Cannot write-protect text "
522: "segment: %s", obj->path, xstrerror(errno));
523: return -1;
524: }
525: }
526: /* Process the PLT relocations. */
527: if (obj->pltrel != NULL) {
528: const Elf_Rel *rel;
529: for (rel = obj->pltrel; rel < obj->pltrellim; ++rel) {
530: Elf_RelA ourrela;
531: ourrela.r_info = rel->r_info;
532: ourrela.r_offset = rel->r_offset;
533: ourrela.r_addend =
534: *(Elf_Word *)(obj->relocbase +
535: rel->r_offset);
536: if (_rtld_relocate_plt_object(obj, &ourrela,
537: NULL, bind_now, dodebug) < 0)
538: ok = 0;
539: }
540: }
541: if (obj->pltrela != NULL) {
542: const Elf_RelA *rela;
543: for (rela = obj->pltrela; rela < obj->pltrelalim;
544: ++rela) {
545: if (_rtld_relocate_plt_object(obj, rela,
546: NULL, bind_now, dodebug) < 0)
547: ok = 0;
548: }
549: }
550: if (!ok)
551: return -1;
552:
553:
554: /* Set some sanity-checking numbers in the Obj_Entry. */
555: obj->magic = RTLD_MAGIC;
556: obj->version = RTLD_VERSION;
557:
558: /* Fill in the dynamic linker entry points. */
559: obj->dlopen = _rtld_dlopen;
560: obj->dlsym = _rtld_dlsym;
561: obj->dlerror = _rtld_dlerror;
562: obj->dlclose = _rtld_dlclose;
1.1 cgd 563:
1.11 christos 564: /* Set the special PLTGOT entries. */
565: if (obj->pltgot != NULL) {
1.1 cgd 566: #if defined(__i386__)
1.11 christos 567: obj->pltgot[1] = (Elf_Addr) obj;
568: obj->pltgot[2] = (Elf_Addr) & _rtld_bind_start;
1.1 cgd 569: #endif
570: #if defined(__alpha__)
1.11 christos 571: /*
572: * This function will be called to perform the
573: * relocation.
574: */
575: obj->pltgot[2] = (Elf_Addr) & _rtld_bind_start;
576: /* Identify this shared object */
577: obj->pltgot[3] = (Elf_Addr) obj;
1.2 mhitch 578: #endif
579: #if defined(__mips__)
1.11 christos 580: _rtld_relocate_mips_got(obj);
1.2 mhitch 581:
1.11 christos 582: obj->pltgot[0] = (Elf_Addr) & _rtld_bind_start;
583: /* XXX only if obj->pltgot[1] & 0x80000000 ?? */
584: obj->pltgot[1] |= (Elf_Addr) obj;
1.3 tsubai 585: #endif
586: #if defined(__powerpc__)
1.11 christos 587: _rtld_setup_powerpc_plt(obj);
1.9 pk 588: #endif
589: #if defined(__sparc__)
1.11 christos 590: /*
591: * PLTGOT is the PLT on the sparc.
592: * The first entry holds the call the dynamic linker.
1.13 pk 593: * We construct a `call' sequence that transfers
1.11 christos 594: * to `_rtld_bind_start()'.
595: * The second entry holds the object identification.
596: * Note: each PLT entry is three words long.
597: */
1.13 pk 598: #define SAVE 0x9de3bfc0 /* i.e. `save %sp,-64,%sp' */
599: #define CALL 0x40000000
600: #define NOP 0x01000000
601: obj->pltgot[0] = SAVE;
602: obj->pltgot[1] = CALL |
1.11 christos 603: ((Elf_Addr)&_rtld_bind_start -
1.13 pk 604: (Elf_Addr)&obj->pltgot[1]) >> 2;
605: obj->pltgot[2] = NOP;
606:
1.11 christos 607: obj->pltgot[3] = (Elf_Addr) obj;
1.1 cgd 608: #endif
1.11 christos 609: }
1.1 cgd 610: }
611:
1.11 christos 612: return 0;
1.1 cgd 613: }
CVSweb <webmaster@jp.NetBSD.org>