[BACK]Return to reloc.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / libexec / ld.elf_so

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>