Home | History | Annotate | Line # | Download | only in ld.elf_so
reloc.c revision 1.7
      1 /*	$NetBSD: reloc.c,v 1.7 1999/02/12 17:52:07 tv Exp $	*/
      2 
      3 /*
      4  * Copyright 1996 John D. Polstra.
      5  * Copyright 1996 Matt Thomas <matt (at) 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 (at) 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 
     55 #if defined(__alpha__) || defined(__powerpc__) || defined(__i386__)
     56 /*
     57  * XXX: These don't work for the alpha and i386; don't know about powerpc
     58  *	The alpha and the i386 avoid the problem by compiling everything PIC.
     59  *	These relocation are supposed to be writing the address of the
     60  *	function to be called on the bss.rel or bss.rela segment, but:
     61  *		- st_size == 0
     62  *		- on the i386 at least the call instruction is a direct call
     63  *		  not an indirect call.
     64  */
     65 static int
     66 _rtld_do_copy_relocation(
     67     const Obj_Entry *dstobj,
     68     const Elf_RelA *rela)
     69 {
     70     void *dstaddr = (void *) (dstobj->relocbase + rela->r_offset);
     71     const Elf_Sym *dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info);
     72     const char *name = dstobj->strtab + dstsym->st_name;
     73     unsigned long hash = _rtld_elf_hash(name);
     74     size_t size = dstsym->st_size;
     75     const void *srcaddr;
     76     const Elf_Sym *srcsym;
     77     Obj_Entry *srcobj;
     78 
     79     for (srcobj = dstobj->next;  srcobj != NULL;  srcobj = srcobj->next)
     80 	if ((srcsym = _rtld_symlook_obj(name, hash, srcobj, false)) != NULL)
     81 	    break;
     82 
     83     if (srcobj == NULL) {
     84 	_rtld_error("Undefined symbol \"%s\" referenced from COPY"
     85 	      " relocation in %s", name, dstobj->path);
     86 	return -1;
     87     }
     88 
     89     srcaddr = (const void *) (srcobj->relocbase + srcsym->st_value);
     90     memcpy(dstaddr, srcaddr, size);
     91 #ifdef RTLD_DEBUG_RELOC
     92     dbg("COPY %s %s %s --> src=%p dst=%p *dst= %p size %d",
     93 	dstobj->path, srcobj->path, name, (void *)srcaddr, (void *)dstaddr,
     94 	(void *)*(long *)dstaddr, size);
     95 #endif
     96     return 0;
     97 }
     98 #endif /* __alpha__ || __powerpc__ || __i386__ */
     99 
    100 /*
    102  * Process the special R_xxx_COPY relocations in the main program.  These
    103  * copy data from a shared object into a region in the main program's BSS
    104  * segment.
    105  *
    106  * Returns 0 on success, -1 on failure.
    107  */
    108 int
    109 _rtld_do_copy_relocations(
    110     const Obj_Entry *dstobj)
    111 {
    112     assert(dstobj->mainprog);	/* COPY relocations are invalid elsewhere */
    113 
    114 #if defined(__alpha__) || defined(__powerpc__) || defined(__i386__)
    115     if (dstobj->rel != NULL) {
    116 	const Elf_Rel *rel;
    117 	for (rel = dstobj->rel;  rel < dstobj->rellim;  ++rel) {
    118 	    if (ELF_R_TYPE(rel->r_info) == R_TYPE(COPY)) {
    119 		Elf_RelA ourrela;
    120 		ourrela.r_info = rel->r_info;
    121 		ourrela.r_offset = rel->r_offset;
    122 		ourrela.r_addend = 0;
    123 		if (_rtld_do_copy_relocation(dstobj, &ourrela) < 0)
    124 		    return -1;
    125 	    }
    126 	}
    127     }
    128 
    129     if (dstobj->rela != NULL) {
    130 	const Elf_RelA *rela;
    131 	for (rela = dstobj->rela;  rela < dstobj->relalim;  ++rela) {
    132 	    if (ELF_R_TYPE(rela->r_info) == R_TYPE(COPY)) {
    133 		if (_rtld_do_copy_relocation(dstobj, rela) < 0)
    134 		    return -1;
    135 	    }
    136 	}
    137     }
    138 #endif /* __alpha__ || __powerpc__ || __i386__ */
    139 
    140     return 0;
    141 }
    142 
    143 static int
    145 _rtld_relocate_nonplt_object(
    146     const Obj_Entry *obj,
    147     const Elf_RelA *rela)
    148 {
    149     Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
    150 
    151     switch (ELF_R_TYPE(rela->r_info)) {
    152 
    153     case R_TYPE(NONE):
    154 	break;
    155 
    156 #ifdef __i386__
    157     case R_TYPE(GOT32): {
    158 	const Elf_Sym *def;
    159 	const Obj_Entry *defobj;
    160 
    161 	def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, &defobj, false);
    162 	if (def == NULL)
    163 	    return -1;
    164 
    165 	if (*where != (Elf_Addr) (defobj->relocbase + def->st_value))
    166 	    *where = (Elf_Addr) (defobj->relocbase + def->st_value);
    167 #ifdef RTLD_DEBUG_RELOC
    168 	dbg("GOT32 %s in %s --> %p in %s",
    169 	    defobj->strtab + def->st_name, obj->path,
    170 	    (void *)*where, defobj->path);
    171 #endif
    172 	break;
    173     }
    174 
    175     case R_TYPE(PC32):
    176 	/*
    177 	 * I don't think the dynamic linker should ever see this
    178 	 * type of relocation.  But the binutils-2.6 tools sometimes
    179 	 * generate it.
    180 	 */
    181     {
    182 	const Elf_Sym *def;
    183 	const Obj_Entry *defobj;
    184 
    185 	def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, &defobj, false);
    186 	if (def == NULL)
    187 	    return -1;
    188 
    189 	*where += (Elf_Addr) (defobj->relocbase + def->st_value)
    190 	    - (Elf_Addr) where;
    191 #ifdef RTLD_DEBUG_RELOC
    192 	dbg("PC32 %s in %s --> %p in %s",
    193 	    defobj->strtab + def->st_name, obj->path,
    194 	    (void *)*where, defobj->path);
    195 #endif
    196 	break;
    197     }
    198 
    199     case R_TYPE(32): {
    200 	const Elf_Sym *def;
    201 	const Obj_Entry *defobj;
    202 
    203 	def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, &defobj, false);
    204 	if (def == NULL)
    205 	    return -1;
    206 
    207 	*where += (Elf_Addr)(defobj->relocbase + def->st_value);
    208 #ifdef RTLD_DEBUG_RELOC
    209 	dbg("32 %s in %s --> %p in %s",
    210 	    defobj->strtab + def->st_name, obj->path,
    211 	    (void *)*where, defobj->path);
    212 #endif
    213 	break;
    214     }
    215 #endif /* __i386__ */
    216 
    217 #ifdef __alpha__
    218     case R_ALPHA_REFQUAD: {
    219 	const Elf_Sym *def;
    220 	const Obj_Entry *defobj;
    221 	Elf_Addr tmp_value;
    222 
    223 	def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, &defobj, false);
    224 	if (def == NULL)
    225 	    return -1;
    226 
    227 	tmp_value = (Elf_Addr) (defobj->relocbase + def->st_value)
    228 	    + *where + rela->r_addend;
    229 	if (*where != tmp_value)
    230 	    *where = tmp_value;
    231 #ifdef RTLD_DEBUG_RELOC
    232 	dbg("REFQUAD %s in %s --> %p in %s",
    233 	    defobj->strtab + def->st_name, obj->path,
    234 	    (void *)*where, defobj->path);
    235 #endif
    236 	break;
    237     }
    238 #endif /* __alpha__ */
    239 
    240 #if defined(__i386__) || defined(__alpha__)
    241     case R_TYPE(GLOB_DAT):
    242     {
    243 	const Elf_Sym *def;
    244 	const Obj_Entry *defobj;
    245 
    246 	def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, &defobj, false);
    247 	if (def == NULL)
    248 	    return -1;
    249 
    250 	if (*where != (Elf_Addr) (defobj->relocbase + def->st_value))
    251 	    *where = (Elf_Addr) (defobj->relocbase + def->st_value);
    252 #ifdef RTLD_DEBUG_RELOC
    253 	dbg("GLOB_DAT %s in %s --> %p in %s",
    254 	    defobj->strtab + def->st_name, obj->path,
    255 	    (void *)*where, defobj->path);
    256 #endif
    257 	break;
    258     }
    259 
    260     case R_TYPE(RELATIVE): {
    261 	extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
    262 	extern Elf_Dyn _DYNAMIC;
    263 
    264 	if (obj != &_rtld_objself ||
    265 	    (caddr_t)where < (caddr_t)_GLOBAL_OFFSET_TABLE_ ||
    266 	    (caddr_t)where >= (caddr_t)&_DYNAMIC) {
    267 	    *where += (Elf_Addr) obj->relocbase;
    268 #ifdef RTLD_DEBUG_RELOC
    269 	    dbg("RELATIVE in %s --> %p", obj->path, (void *)*where);
    270 #endif
    271 	}
    272 #ifdef RTLD_DEBUG_RELOC
    273 	else
    274 	    dbg("RELATIVE in %s stays at %p", obj->path, (void *)*where);
    275 #endif
    276 	break;
    277     }
    278 
    279     case R_TYPE(COPY): {
    280 	/*
    281 	 * These are deferred until all other relocations have
    282 	 * been done.  All we do here is make sure that the COPY
    283 	 * relocation is not in a shared library.  They are allowed
    284 	 * only in executable files.
    285 	 */
    286 	if (!obj->mainprog) {
    287 	    _rtld_error("%s: Unexpected R_COPY relocation in shared library",
    288 		  obj->path);
    289 	    return -1;
    290 	}
    291 #ifdef RTLD_DEBUG_RELOC
    292 	dbg("COPY (avoid in main)");
    293 #endif
    294 	break;
    295     }
    296 #endif /* __i386__ || __alpha__ */
    297 
    298 #ifdef __mips__
    299     case R_TYPE(REL32): {
    300     		/* 32-bit PC-relative reference */
    301 
    302         const Elf_Sym *def;
    303         const Obj_Entry *defobj;
    304 
    305 	def = obj->symtab + ELF_R_SYM(rela->r_info);
    306 
    307         if (ELF_SYM_BIND(def->st_info) == Elf_estb_local &&
    308           (ELF_SYM_TYPE(def->st_info) == Elf_estt_section ||
    309            ELF_SYM_TYPE(def->st_info) == Elf_estt_notype)) {
    310             *where += (Elf_Addr) obj->relocbase;
    311 #ifdef RTLD_DEBUG_RELOC
    312 	    dbg("REL32 in %s --> %p", obj->path, (void *)*where);
    313 #endif
    314         } else {
    315 /* XXX maybe do something re: bootstrapping? */
    316             def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj,
    317 	        &defobj, false);
    318             if (def == NULL)
    319                 return -1;
    320 	    *where += (Elf_Addr)(defobj->relocbase + def->st_value);
    321 #ifdef RTLD_DEBUG_RELOC
    322 	    dbg("REL32 %s in %s --> %p in %s",
    323 		defobj->strtab + def->st_name, obj->path,
    324 		(void *)*where, defobj->path);
    325 #endif
    326         }
    327         break;
    328     }
    329 
    330 #endif /* mips */
    331 
    332 #ifdef __powerpc__
    333     case R_TYPE(32):		/* word32 S + A */
    334     case R_TYPE(GLOB_DAT): {	/* word32 S + A */
    335 	const Elf_Sym *def;
    336 	const Obj_Entry *defobj;
    337 	Elf_Addr x;
    338 
    339 	def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, &defobj, false);
    340 	if (def == NULL)
    341 	    return -1;
    342 
    343 	x = (Elf_Addr)(defobj->relocbase + def->st_value + rela->r_addend);
    344 
    345 	if (*where != x)
    346 	    *where = x;
    347 #ifdef RTLD_DEBUG_RELOC
    348 	dbg("32/GLOB_DAT %s in %s --> %p in %s",
    349 	    defobj->strtab + def->st_name, obj->path,
    350 	    (void *)*where, defobj->path);
    351 #endif
    352 	break;
    353     }
    354 
    355     case R_TYPE(COPY):
    356 #ifdef RTLD_DEBUG_RELOC
    357 	dbg("COPY");
    358 #endif
    359 	break;
    360 
    361     case R_TYPE(JMP_SLOT):
    362 #ifdef RTLD_DEBUG_RELOC
    363 	dbg("JMP_SLOT");
    364 #endif
    365 	break;
    366 
    367     case R_TYPE(RELATIVE): {	/* word32 B + A */
    368 	if (obj == &_rtld_objself &&
    369 	    *where == (Elf_Addr)obj->relocbase + rela->r_addend)
    370 	    break;	/* GOT - already done */
    371 
    372 	*where = (Elf_Addr)obj->relocbase + rela->r_addend;
    373 #ifdef RTLD_DEBUG_RELOC
    374 	dbg("RELATIVE in %s --> %p", obj->path, (void *)*where);
    375 #endif
    376 	break;
    377     }
    378 #endif /* __powerpc__ */
    379 
    380     default: {
    381 	const Elf_Sym *def;
    382 	const Obj_Entry *defobj;
    383 
    384 	def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, &defobj, true);
    385 	dbg("sym = %lu, type = %lu, offset = %p, addend = %p, contents = %p, symbol = %s",
    386 	    (u_long)ELF_R_SYM(rela->r_info), (u_long)ELF_R_TYPE(rela->r_info),
    387 	    (void *)rela->r_offset, (void *)rela->r_addend, (void *)*where,
    388 	    def ? defobj->strtab + def->st_name : "??");
    389 	_rtld_error("%s: Unsupported relocation type %d in non-PLT relocations\n",
    390 	      obj->path, ELF_R_TYPE(rela->r_info));
    391 	return -1;
    392     }
    393     }
    394     return 0;
    395 }
    396 
    397 static int
    399 _rtld_relocate_plt_object(
    400     const Obj_Entry *obj,
    401     const Elf_RelA *rela,
    402     bool bind_now)
    403 {
    404     Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
    405     Elf_Addr new_value;
    406 
    407     /* Fully resolve procedure addresses now */
    408 
    409 #if defined(__powerpc__)
    410     return _rtld_reloc_powerpc_plt(obj, rela, bind_now);
    411 #endif
    412 
    413 #if defined(__alpha__)	|| defined(__i386__) /* (jrs) */
    414     if (bind_now || obj->pltgot == NULL) {
    415 	const Elf_Sym *def;
    416 	const Obj_Entry *defobj;
    417 
    418 	assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT));
    419 
    420 	def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, &defobj, true);
    421 	if (def == NULL)
    422 	    return -1;
    423 
    424 	new_value = (Elf_Addr) (defobj->relocbase + def->st_value);
    425 #ifdef RTLD_DEBUG_RELOC
    426 	dbg("bind now %d/fixup in %s --> old=%p new=%p",
    427 	    (int)bind_now,
    428 	    defobj->strtab + def->st_name,
    429 	    (void *)*where, (void *)new_value);
    430 #endif
    431     } else
    432 #endif	/* __alpha__ (jrs) */
    433     if (!obj->mainprog) {
    434 	/* Just relocate the GOT slots pointing into the PLT */
    435 	new_value = *where + (Elf_Addr) (obj->relocbase);
    436 #ifdef RTLD_DEBUG_RELOC
    437 	dbg("fixup !main in %s --> %p", obj->path, (void *)*where);
    438 #endif
    439     } else {
    440 #ifdef __i386__
    441  	new_value = *where + (Elf_Addr) (obj->relocbase);
    442 #ifdef RTLD_DEBUG_RELOC
    443 	dbg("fixup main in %s --> %p", obj->path, (void *)*where);
    444 #endif
    445 #else
    446 	return 0;
    447 #endif
    448     }
    449     /*
    450      * Since this page is probably copy-on-write, let's not write
    451      * it unless we really really have to.
    452      */
    453     if (*where != new_value)
    454 	*where = new_value;
    455     return 0;
    456 }
    457 
    458 caddr_t
    460 _rtld_bind(
    461     const Obj_Entry *obj,
    462     Elf_Word reloff)
    463 {
    464     const Elf_RelA *rela;
    465     Elf_RelA ourrela;
    466 
    467     if (obj->pltrel != NULL) {
    468 	ourrela.r_info =   ((const Elf_Rel *) ((caddr_t) obj->pltrel + reloff))->r_info;
    469 	ourrela.r_offset = ((const Elf_Rel *) ((caddr_t) obj->pltrel + reloff))->r_offset;
    470 	rela = &ourrela;
    471     } else {
    472 	rela = (const Elf_RelA *) ((caddr_t) obj->pltrela + reloff);
    473     }
    474 
    475     if (_rtld_relocate_plt_object(obj, rela, true) < 0)
    476 	_rtld_die();
    477 
    478     return *(caddr_t *)(obj->relocbase + rela->r_offset);
    479 }
    480 
    481 /*
    483  * Relocate newly-loaded shared objects.  The argument is a pointer to
    484  * the Obj_Entry for the first such object.  All objects from the first
    485  * to the end of the list of objects are relocated.  Returns 0 on success,
    486  * or -1 on failure.
    487  */
    488 int
    489 _rtld_relocate_objects(
    490     Obj_Entry *first,
    491     bool bind_now)
    492 {
    493     Obj_Entry *obj;
    494     int ok = 1;
    495 
    496     for (obj = first;  obj != NULL;  obj = obj->next) {
    497 
    498 	if (obj->nbuckets == 0 || obj->nchains == 0
    499 	        || obj->buckets == NULL || obj->symtab == NULL
    500 	        || obj->strtab == NULL) {
    501 	    _rtld_error("%s: Shared object has no run-time symbol table",
    502 			obj->path);
    503 	    return -1;
    504 	}
    505 
    506 	dbg(" relocating %s (%ld/%ld rel/rela, %ld/%ld plt rel/rela)",
    507 	    obj->path,
    508 	    (long)(obj->rellim - obj->rel), (long)(obj->relalim - obj->rela),
    509 	    (long)(obj->pltrellim - obj->pltrel),
    510 	    (long)(obj->pltrelalim - obj->pltrela));
    511 
    512 	if (obj->textrel) {
    513 	    /* There are relocations to the write-protected text segment. */
    514 	    if (mprotect(obj->mapbase, obj->textsize,
    515 			 PROT_READ|PROT_WRITE|PROT_EXEC) == -1) {
    516 		_rtld_error("%s: Cannot write-enable text segment: %s",
    517 			    obj->path, xstrerror(errno));
    518 		return -1;
    519 	    }
    520 	}
    521 
    522 	if (obj->rel != NULL) {
    523 	    /* Process the non-PLT relocations. */
    524 	    const Elf_Rel *rel;
    525 	    for (rel = obj->rel;  rel < obj->rellim;  ++rel) {
    526 		Elf_RelA ourrela;
    527 		ourrela.r_info   = rel->r_info;
    528 		ourrela.r_offset = rel->r_offset;
    529 #if defined(__mips__)
    530 		/* rel->r_offset is not valid on mips? */
    531 		if (ELF_R_TYPE(ourrela.r_info) == R_TYPE(NONE))
    532 		    ourrela.r_addend = 0;
    533 		else
    534 #endif
    535 		ourrela.r_addend = *(Elf_Word *) (obj->relocbase + rel->r_offset);
    536 
    537 		if (_rtld_relocate_nonplt_object(obj, &ourrela) < 0)
    538 		    ok = 0;
    539 	    }
    540 	}
    541 
    542 	if (obj->rela != NULL) {
    543 	    /* Process the non-PLT relocations. */
    544 	    const Elf_RelA *rela;
    545 	    for (rela = obj->rela;  rela < obj->relalim;  ++rela) {
    546 		if (_rtld_relocate_nonplt_object(obj, rela) < 0)
    547 		    ok = 0;
    548 	    }
    549 	}
    550 
    551 	if (obj->textrel) {	/* Re-protected the text segment. */
    552 	    if (mprotect(obj->mapbase, obj->textsize,
    553 			 PROT_READ|PROT_EXEC) == -1) {
    554 		_rtld_error("%s: Cannot write-protect text segment: %s",
    555 			    obj->path, xstrerror(errno));
    556 		return -1;
    557 	    }
    558 	}
    559 
    560 	/* Process the PLT relocations. */
    561 	if (obj->pltrel != NULL) {
    562 	    const Elf_Rel *rel;
    563 	    for (rel = obj->pltrel; rel < obj->pltrellim;  ++rel) {
    564 		Elf_RelA ourrela;
    565 		ourrela.r_info   = rel->r_info;
    566 		ourrela.r_offset = rel->r_offset;
    567 		ourrela.r_addend = *(Elf_Word *) (obj->relocbase + rel->r_offset);
    568 		if (_rtld_relocate_plt_object(obj, &ourrela, bind_now) < 0)
    569 		    ok = 0;
    570 	    }
    571 	}
    572 
    573 	if (obj->pltrela != NULL) {
    574 	    const Elf_RelA *rela;
    575 	    for (rela = obj->pltrela;  rela < obj->pltrelalim;  ++rela) {
    576 		if (_rtld_relocate_plt_object(obj, rela, bind_now) < 0)
    577 		    ok = 0;
    578 	    }
    579 	}
    580 
    581 	if (!ok)
    582 	    return -1;
    583 
    584 
    585 	/* Set some sanity-checking numbers in the Obj_Entry. */
    586 	obj->magic = RTLD_MAGIC;
    587 	obj->version = RTLD_VERSION;
    588 
    589 	/* Fill in the dynamic linker entry points. */
    590 	obj->dlopen  = _rtld_dlopen;
    591 	obj->dlsym   = _rtld_dlsym;
    592 	obj->dlerror = _rtld_dlerror;
    593 	obj->dlclose = _rtld_dlclose;
    594 
    595 	/* Set the special PLTGOT entries. */
    596 	if (obj->pltgot != NULL) {
    597 #if defined(__i386__)
    598 	    obj->pltgot[1] = (Elf_Addr) obj;
    599 	    obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
    600 #endif
    601 #if defined(__alpha__)
    602 	    /* This function will be called to perform the relocation.  */
    603 	    obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
    604 	    /* Identify this shared object */
    605 	    obj->pltgot[3] = (Elf_Addr) obj;
    606 #endif
    607 #if defined(__mips__)
    608 	    _rtld_relocate_mips_got(obj);
    609 
    610 	    obj->pltgot[0] = (Elf_Addr) &_rtld_bind_start;
    611 	    /* XXX only if obj->pltgot[1] & 0x80000000 ?? */
    612 	    obj->pltgot[1] |= (Elf_Addr) obj;
    613 #endif
    614 #if defined(__powerpc__)
    615 	    _rtld_setup_powerpc_plt(obj);
    616 #endif
    617 	}
    618     }
    619 
    620     return 0;
    621 }
    622