[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.97

1.97    ! pooka       1: /*     $NetBSD: reloc.c,v 1.96 2008/07/29 16:27:01 matt 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:
1.85      skrll      40: #include <sys/cdefs.h>
                     41: #ifndef lint
1.97    ! pooka      42: __RCSID("$NetBSD: reloc.c,v 1.96 2008/07/29 16:27:01 matt Exp $");
1.85      skrll      43: #endif /* not lint */
                     44:
1.1       cgd        45: #include <err.h>
                     46: #include <errno.h>
                     47: #include <fcntl.h>
                     48: #include <stdarg.h>
                     49: #include <stdio.h>
                     50: #include <stdlib.h>
                     51: #include <string.h>
                     52: #include <unistd.h>
                     53: #include <sys/types.h>
                     54: #include <sys/mman.h>
                     55: #include <dirent.h>
                     56:
                     57: #include "debug.h"
                     58: #include "rtld.h"
                     59:
1.14      pk         60: #ifndef RTLD_INHIBIT_COPY_RELOCS
1.80      skrll      61: static int _rtld_do_copy_relocation(const Obj_Entry *, const Elf_Rela *);
1.16      christos   62:
1.1       cgd        63: static int
1.80      skrll      64: _rtld_do_copy_relocation(const Obj_Entry *dstobj, const Elf_Rela *rela)
1.1       cgd        65: {
1.11      christos   66:        void           *dstaddr = (void *)(dstobj->relocbase + rela->r_offset);
                     67:        const Elf_Sym  *dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info);
                     68:        const char     *name = dstobj->strtab + dstsym->st_name;
                     69:        unsigned long   hash = _rtld_elf_hash(name);
                     70:        size_t          size = dstsym->st_size;
                     71:        const void     *srcaddr;
1.37      matt       72:        const Elf_Sym  *srcsym = NULL;
1.11      christos   73:        Obj_Entry      *srcobj;
                     74:
                     75:        for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next)
1.72      mycroft    76:                if ((srcsym = _rtld_symlook_obj(name, hash, srcobj, false)) != NULL)
1.11      christos   77:                        break;
                     78:
                     79:        if (srcobj == NULL) {
                     80:                _rtld_error("Undefined symbol \"%s\" referenced from COPY"
                     81:                    " relocation in %s", name, dstobj->path);
1.14      pk         82:                return (-1);
1.11      christos   83:        }
                     84:        srcaddr = (const void *)(srcobj->relocbase + srcsym->st_value);
                     85:        (void)memcpy(dstaddr, srcaddr, size);
1.84      petrov     86:        rdbg(("COPY %s %s %s --> src=%p dst=%p size %ld",
1.11      christos   87:            dstobj->path, srcobj->path, name, (void *)srcaddr,
1.84      petrov     88:            (void *)dstaddr, (long)size));
1.14      pk         89:        return (0);
1.1       cgd        90: }
1.14      pk         91: #endif /* RTLD_INHIBIT_COPY_RELOCS */
1.11      christos   92:
                     93:
1.1       cgd        94: /*
                     95:  * Process the special R_xxx_COPY relocations in the main program.  These
                     96:  * copy data from a shared object into a region in the main program's BSS
                     97:  * segment.
                     98:  *
                     99:  * Returns 0 on success, -1 on failure.
                    100:  */
                    101: int
1.80      skrll     102: _rtld_do_copy_relocations(const Obj_Entry *dstobj)
1.1       cgd       103: {
1.14      pk        104: #ifndef RTLD_INHIBIT_COPY_RELOCS
                    105:
                    106:        /* COPY relocations are invalid elsewhere */
1.64      mycroft   107:        assert(!dstobj->isdynamic);
1.1       cgd       108:
1.11      christos  109:        if (dstobj->rel != NULL) {
                    110:                const Elf_Rel  *rel;
                    111:                for (rel = dstobj->rel; rel < dstobj->rellim; ++rel) {
                    112:                        if (ELF_R_TYPE(rel->r_info) == R_TYPE(COPY)) {
1.35      kleink    113:                                Elf_Rela        ourrela;
1.11      christos  114:                                ourrela.r_info = rel->r_info;
                    115:                                ourrela.r_offset = rel->r_offset;
                    116:                                ourrela.r_addend = 0;
                    117:                                if (_rtld_do_copy_relocation(dstobj,
1.66      mycroft   118:                                    &ourrela) < 0)
1.14      pk        119:                                        return (-1);
1.11      christos  120:                        }
                    121:                }
                    122:        }
                    123:        if (dstobj->rela != NULL) {
1.35      kleink    124:                const Elf_Rela *rela;
1.11      christos  125:                for (rela = dstobj->rela; rela < dstobj->relalim; ++rela) {
                    126:                        if (ELF_R_TYPE(rela->r_info) == R_TYPE(COPY)) {
1.66      mycroft   127:                                if (_rtld_do_copy_relocation(dstobj, rela) < 0)
1.14      pk        128:                                        return (-1);
1.11      christos  129:                        }
                    130:                }
1.1       cgd       131:        }
1.14      pk        132: #endif /* RTLD_INHIBIT_COPY_RELOCS */
1.1       cgd       133:
1.14      pk        134:        return (0);
1.1       cgd       135: }
1.9       pk        136:
1.1       cgd       137: /*
                    138:  * Relocate newly-loaded shared objects.  The argument is a pointer to
                    139:  * the Obj_Entry for the first such object.  All objects from the first
                    140:  * to the end of the list of objects are relocated.  Returns 0 on success,
                    141:  * or -1 on failure.
                    142:  */
                    143: int
1.80      skrll     144: _rtld_relocate_objects(Obj_Entry *first, bool bind_now)
1.1       cgd       145: {
1.16      christos  146:        Obj_Entry *obj;
1.77      mycroft   147:        int ok = 1;
1.1       cgd       148:
1.11      christos  149:        for (obj = first; obj != NULL; obj = obj->next) {
1.16      christos  150:                if (obj->nbuckets == 0 || obj->nchains == 0 ||
                    151:                    obj->buckets == NULL || obj->symtab == NULL ||
                    152:                    obj->strtab == NULL) {
1.11      christos  153:                        _rtld_error("%s: Shared object has no run-time"
                    154:                            " symbol table", obj->path);
                    155:                        return -1;
                    156:                }
1.66      mycroft   157:                rdbg((" relocating %s (%ld/%ld rel/rela, %ld/%ld plt rel/rela)",
1.11      christos  158:                    obj->path,
                    159:                    (long)(obj->rellim - obj->rel),
                    160:                    (long)(obj->relalim - obj->rela),
                    161:                    (long)(obj->pltrellim - obj->pltrel),
1.16      christos  162:                    (long)(obj->pltrelalim - obj->pltrela)));
1.11      christos  163:
                    164:                if (obj->textrel) {
                    165:                        /*
                    166:                         * There are relocations to the write-protected text
                    167:                         * segment.
                    168:                         */
                    169:                        if (mprotect(obj->mapbase, obj->textsize,
                    170:                                PROT_READ | PROT_WRITE | PROT_EXEC) == -1) {
                    171:                                _rtld_error("%s: Cannot write-enable text "
                    172:                                    "segment: %s", obj->path, xstrerror(errno));
                    173:                                return -1;
                    174:                        }
                    175:                }
1.71      mycroft   176:                dbg(("doing non-PLT relocations"));
1.76      junyoung  177:                if (_rtld_relocate_nonplt_objects(obj) < 0)
1.77      mycroft   178:                        ok = 0;
1.11      christos  179:                if (obj->textrel) {     /* Re-protected the text segment. */
                    180:                        if (mprotect(obj->mapbase, obj->textsize,
                    181:                                     PROT_READ | PROT_EXEC) == -1) {
                    182:                                _rtld_error("%s: Cannot write-protect text "
                    183:                                    "segment: %s", obj->path, xstrerror(errno));
                    184:                                return -1;
                    185:                        }
                    186:                }
1.71      mycroft   187:                dbg(("doing lazy PLT binding"));
1.76      junyoung  188:                if (_rtld_relocate_plt_lazy(obj) < 0)
1.77      mycroft   189:                        ok = 0;
1.83      skrll     190: #if defined(__hppa__)
                    191:                bind_now = 1;
                    192: #endif
1.82      skrll     193:                if (bind_now) {
                    194:                        dbg(("doing immediate PLT binding"));
1.76      junyoung  195:                        if (_rtld_relocate_plt_objects(obj) < 0)
1.77      mycroft   196:                                ok = 0;
1.82      skrll     197:                }
1.77      mycroft   198:                if (!ok)
                    199:                        return -1;
                    200:
1.96      matt      201:                (void)dlerror(); /* clear any errors since all is good */
1.11      christos  202:
                    203:                /* Set some sanity-checking numbers in the Obj_Entry. */
                    204:                obj->magic = RTLD_MAGIC;
                    205:                obj->version = RTLD_VERSION;
                    206:
                    207:                /* Fill in the dynamic linker entry points. */
1.81      skrll     208:                obj->dlopen = dlopen;
                    209:                obj->dlsym = dlsym;
                    210:                obj->dlerror = dlerror;
                    211:                obj->dlclose = dlclose;
                    212:                obj->dladdr = dladdr;
1.97    ! pooka     213:                obj->dlinfo = dlinfo;
1.1       cgd       214:
1.71      mycroft   215:                dbg(("fixing up PLTGOT"));
1.11      christos  216:                /* Set the special PLTGOT entries. */
1.53      mycroft   217:                if (obj->pltgot != NULL)
                    218:                        _rtld_setup_pltgot(obj);
1.1       cgd       219:        }
                    220:
1.11      christos  221:        return 0;
1.1       cgd       222: }

CVSweb <webmaster@jp.NetBSD.org>