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

Annotation of src/libexec/ld.elf_so/headers.c, Revision 1.24

1.24    ! christos    1: /*     $NetBSD: headers.c,v 1.23 2007/12/07 20:34:04 ad Exp $   */
1.1       cgd         2:
                      3: /*
                      4:  * Copyright 1996 John D. Polstra.
                      5:  * Copyright 1996 Matt Thomas <matt@3am-software.com>
1.17      mycroft     6:  * Copyright 2002 Charles M. Hannum <root@ihack.net>
1.1       cgd         7:  * All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
                     19:  *      This product includes software developed by John Polstra.
                     20:  * 4. The name of the author may not be used to endorse or promote products
                     21:  *    derived from this software without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     25:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     26:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     27:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     28:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     29:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     30:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     31:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     32:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     33:  */
                     34:
                     35: /*
                     36:  * Dynamic linker for ELF.
                     37:  *
                     38:  * John Polstra <jdp@polstra.com>.
                     39:  */
                     40:
1.19      skrll      41: #include <sys/cdefs.h>
                     42: #ifndef lint
1.24    ! christos   43: __RCSID("$NetBSD: headers.c,v 1.23 2007/12/07 20:34:04 ad Exp $");
1.19      skrll      44: #endif /* not lint */
                     45:
1.1       cgd        46: #include <err.h>
                     47: #include <errno.h>
                     48: #include <fcntl.h>
                     49: #include <stdarg.h>
                     50: #include <stdio.h>
                     51: #include <stdlib.h>
                     52: #include <string.h>
                     53: #include <unistd.h>
                     54: #include <sys/types.h>
                     55: #include <sys/mman.h>
                     56: #include <dirent.h>
                     57:
                     58: #include "debug.h"
                     59: #include "rtld.h"
                     60:
                     61: /*
                     62:  * Process a shared object's DYNAMIC section, and save the important
                     63:  * information in its Obj_Entry structure.
                     64:  */
                     65: void
1.22      christos   66: _rtld_digest_dynamic(const char *execname, Obj_Entry *obj)
1.1       cgd        67: {
1.4       christos   68:        Elf_Dyn        *dynp;
                     69:        Needed_Entry  **needed_tail = &obj->needed;
                     70:        const Elf_Dyn  *dyn_rpath = NULL;
1.15      mycroft    71:        Elf_Sword       plttype = DT_NULL;
1.8       mycroft    72:        Elf_Addr        relsz = 0, relasz = 0;
1.13      mycroft    73:        Elf_Addr        pltrel = 0, pltrelsz = 0;
1.10      fredette   74:        Elf_Addr        init = 0, fini = 0;
1.4       christos   75:
1.5       kleink     76:        for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; ++dynp) {
1.4       christos   77:                switch (dynp->d_tag) {
                     78:
1.5       kleink     79:                case DT_REL:
1.4       christos   80:                        obj->rel = (const Elf_Rel *)
                     81:                            (obj->relocbase + dynp->d_un.d_ptr);
                     82:                        break;
                     83:
1.5       kleink     84:                case DT_RELSZ:
1.4       christos   85:                        relsz = dynp->d_un.d_val;
                     86:                        break;
                     87:
1.5       kleink     88:                case DT_RELENT:
1.4       christos   89:                        assert(dynp->d_un.d_val == sizeof(Elf_Rel));
                     90:                        break;
                     91:
1.5       kleink     92:                case DT_JMPREL:
1.13      mycroft    93:                        pltrel = dynp->d_un.d_ptr;
1.4       christos   94:                        break;
                     95:
1.5       kleink     96:                case DT_PLTRELSZ:
1.8       mycroft    97:                        pltrelsz = dynp->d_un.d_val;
1.4       christos   98:                        break;
                     99:
1.5       kleink    100:                case DT_RELA:
1.9       kleink    101:                        obj->rela = (const Elf_Rela *)
1.4       christos  102:                            (obj->relocbase + dynp->d_un.d_ptr);
                    103:                        break;
                    104:
1.5       kleink    105:                case DT_RELASZ:
1.4       christos  106:                        relasz = dynp->d_un.d_val;
                    107:                        break;
                    108:
1.5       kleink    109:                case DT_RELAENT:
1.9       kleink    110:                        assert(dynp->d_un.d_val == sizeof(Elf_Rela));
1.4       christos  111:                        break;
                    112:
1.5       kleink    113:                case DT_PLTREL:
1.4       christos  114:                        plttype = dynp->d_un.d_val;
1.13      mycroft   115:                        assert(plttype == DT_REL || plttype == DT_RELA);
1.4       christos  116:                        break;
                    117:
1.5       kleink    118:                case DT_SYMTAB:
1.4       christos  119:                        obj->symtab = (const Elf_Sym *)
                    120:                                (obj->relocbase + dynp->d_un.d_ptr);
                    121:                        break;
                    122:
1.5       kleink    123:                case DT_SYMENT:
1.4       christos  124:                        assert(dynp->d_un.d_val == sizeof(Elf_Sym));
                    125:                        break;
                    126:
1.5       kleink    127:                case DT_STRTAB:
1.4       christos  128:                        obj->strtab = (const char *)
                    129:                            (obj->relocbase + dynp->d_un.d_ptr);
                    130:                        break;
                    131:
1.5       kleink    132:                case DT_STRSZ:
1.4       christos  133:                        obj->strsize = dynp->d_un.d_val;
                    134:                        break;
                    135:
1.5       kleink    136:                case DT_HASH:
1.4       christos  137:                        {
                    138:                                const Elf_Word *hashtab = (const Elf_Word *)
                    139:                                (obj->relocbase + dynp->d_un.d_ptr);
                    140:
                    141:                                obj->nbuckets = hashtab[0];
                    142:                                obj->nchains = hashtab[1];
                    143:                                obj->buckets = hashtab + 2;
                    144:                                obj->chains = obj->buckets + obj->nbuckets;
                    145:                        }
                    146:                        break;
                    147:
1.5       kleink    148:                case DT_NEEDED:
1.4       christos  149:                        {
                    150:                                Needed_Entry *nep = NEW(Needed_Entry);
                    151:
                    152:                                nep->name = dynp->d_un.d_val;
                    153:                                nep->obj = NULL;
                    154:                                nep->next = NULL;
                    155:
                    156:                                *needed_tail = nep;
                    157:                                needed_tail = &nep->next;
                    158:                        }
                    159:                        break;
                    160:
1.5       kleink    161:                case DT_PLTGOT:
1.4       christos  162:                        obj->pltgot = (Elf_Addr *)
                    163:                            (obj->relocbase + dynp->d_un.d_ptr);
                    164:                        break;
                    165:
1.5       kleink    166:                case DT_TEXTREL:
1.4       christos  167:                        obj->textrel = true;
                    168:                        break;
                    169:
1.5       kleink    170:                case DT_SYMBOLIC:
1.4       christos  171:                        obj->symbolic = true;
                    172:                        break;
                    173:
1.5       kleink    174:                case DT_RPATH:
1.4       christos  175:                        /*
                    176:                         * We have to wait until later to process this, because
                    177:                         * we might not have gotten the address of the string
                    178:                         * table yet.
                    179:                         */
                    180:                        dyn_rpath = dynp;
                    181:                        break;
                    182:
1.5       kleink    183:                case DT_SONAME:
1.4       christos  184:                        /* Not used by the dynamic linker. */
                    185:                        break;
                    186:
1.5       kleink    187:                case DT_INIT:
1.10      fredette  188:                        init = dynp->d_un.d_ptr;
1.4       christos  189:                        break;
                    190:
1.5       kleink    191:                case DT_FINI:
1.10      fredette  192:                        fini = dynp->d_un.d_ptr;
1.4       christos  193:                        break;
1.1       cgd       194:
1.20      simonb    195:                /*
                    196:                 * Don't process DT_DEBUG on MIPS as the dynamic section
                    197:                 * is mapped read-only. DT_MIPS_RLD_MAP is used instead.
                    198:                 * XXX: n32/n64 may use DT_DEBUG, not sure yet.
                    199:                 */
                    200: #ifndef __mips__
1.5       kleink    201:                case DT_DEBUG:
1.1       cgd       202: #ifdef RTLD_LOADER
1.4       christos  203:                        dynp->d_un.d_ptr = (Elf_Addr)&_rtld_debug;
1.1       cgd       204: #endif
1.4       christos  205:                        break;
1.20      simonb    206: #endif
1.2       mhitch    207:
1.14      mycroft   208: #ifdef __mips__
1.4       christos  209:                case DT_MIPS_LOCAL_GOTNO:
                    210:                        obj->local_gotno = dynp->d_un.d_val;
                    211:                        break;
                    212:
                    213:                case DT_MIPS_SYMTABNO:
                    214:                        obj->symtabno = dynp->d_un.d_val;
                    215:                        break;
                    216:
                    217:                case DT_MIPS_GOTSYM:
                    218:                        obj->gotsym = dynp->d_un.d_val;
                    219:                        break;
1.2       mhitch    220:
1.4       christos  221:                case DT_MIPS_RLD_MAP:
1.2       mhitch    222: #ifdef RTLD_LOADER
1.4       christos  223:                        *((Elf_Addr *)(dynp->d_un.d_ptr)) = (Elf_Addr)
                    224:                            &_rtld_debug;
1.2       mhitch    225: #endif
1.4       christos  226:                        break;
1.2       mhitch    227: #endif
1.23      ad        228:                case DT_FLAGS_1:
                    229:                        obj->initfirst =
                    230:                            ((dynp->d_un.d_val & DF_1_INITFIRST) != 0);
                    231:                        break;
1.4       christos  232:                }
1.1       cgd       233:        }
                    234:
1.4       christos  235:        obj->rellim = (const Elf_Rel *)((caddr_t)obj->rel + relsz);
1.9       kleink    236:        obj->relalim = (const Elf_Rela *)((caddr_t)obj->rela + relasz);
1.8       mycroft   237:        if (plttype == DT_REL) {
1.13      mycroft   238:                obj->pltrel = (const Elf_Rel *)(obj->relocbase + pltrel);
                    239:                obj->pltrellim = (const Elf_Rel *)(obj->relocbase + pltrel + pltrelsz);
                    240:                obj->pltrelalim = 0;
                    241:                /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL.
                    242:                   Trim rel(a)lim to save time later. */
                    243:                if (obj->rellim && obj->pltrel &&
                    244:                    obj->rellim > obj->pltrel &&
                    245:                    obj->rellim <= obj->pltrellim)
1.11      mycroft   246:                        obj->rellim = obj->pltrel;
1.15      mycroft   247:        } else if (plttype == DT_RELA) {
1.13      mycroft   248:                obj->pltrela = (const Elf_Rela *)(obj->relocbase + pltrel);
                    249:                obj->pltrellim = 0;
                    250:                obj->pltrelalim = (const Elf_Rela *)(obj->relocbase + pltrel + pltrelsz);
                    251:                /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL.
                    252:                   Trim rel(a)lim to save time later. */
                    253:                if (obj->relalim && obj->pltrela &&
                    254:                    obj->relalim > obj->pltrela &&
                    255:                    obj->relalim <= obj->pltrelalim)
1.11      mycroft   256:                        obj->relalim = obj->pltrela;
1.8       mycroft   257:        }
1.10      fredette  258:
                    259: #if defined(RTLD_LOADER) && defined(__HAVE_FUNCTION_DESCRIPTORS)
                    260:        if (init != 0)
1.18      skrll     261:                obj->init = (void (*)(void))
1.10      fredette  262:                    _rtld_function_descriptor_alloc(obj, NULL, init);
                    263:        if (fini != 0)
1.18      skrll     264:                obj->fini = (void (*)(void))
1.10      fredette  265:                    _rtld_function_descriptor_alloc(obj, NULL, fini);
                    266: #else
                    267:        if (init != 0)
1.18      skrll     268:                obj->init = (void (*)(void))
1.10      fredette  269:                    (obj->relocbase + init);
                    270:        if (fini != 0)
1.18      skrll     271:                obj->fini = (void (*)(void))
1.10      fredette  272:                    (obj->relocbase + fini);
                    273: #endif
1.4       christos  274:
                    275:        if (dyn_rpath != NULL) {
1.22      christos  276:                _rtld_add_paths(execname, &obj->rpaths, obj->strtab +
1.12      mycroft   277:                    dyn_rpath->d_un.d_val);
1.4       christos  278:        }
1.1       cgd       279: }
                    280:
                    281: /*
                    282:  * Process a shared object's program header.  This is used only for the
                    283:  * main program, when the kernel has already loaded the main program
                    284:  * into memory before calling the dynamic linker.  It creates and
                    285:  * returns an Obj_Entry structure.
                    286:  */
                    287: Obj_Entry *
1.18      skrll     288: _rtld_digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry)
1.1       cgd       289: {
1.6       mycroft   290:        Obj_Entry      *obj;
1.4       christos  291:        const Elf_Phdr *phlimit = phdr + phnum;
                    292:        const Elf_Phdr *ph;
                    293:        int             nsegs = 0;
1.24    ! christos  294:        ptrdiff_t       relocoffs = 0;
        !           295:        Elf_Addr        vaddr;
1.4       christos  296:
1.6       mycroft   297:        obj = _rtld_obj_new();
1.4       christos  298:        for (ph = phdr; ph < phlimit; ++ph) {
1.24    ! christos  299:                vaddr = ph->p_vaddr + relocoffs;
        !           300:                dbg(("headers: relocoffs = %lx\n", (long)relocoffs));
1.4       christos  301:                switch (ph->p_type) {
                    302:
1.5       kleink    303:                case PT_PHDR:
1.24    ! christos  304:                        relocoffs = (char *)phdr - (char *)ph->p_vaddr;
1.6       mycroft   305:                        break;
                    306:
                    307:                case PT_INTERP:
1.24    ! christos  308:                        obj->interp = (const char *)vaddr;
1.4       christos  309:                        break;
                    310:
1.5       kleink    311:                case PT_LOAD:
1.4       christos  312:                        assert(nsegs < 2);
                    313:                        if (nsegs == 0) {       /* First load segment */
1.24    ! christos  314:                                obj->vaddrbase = round_down(vaddr);
        !           315:                                obj->mapbase = (caddr_t)obj->vaddrbase;
        !           316:                                obj->relocbase = relocoffs ? (void *)relocoffs :
        !           317:                                    (obj->mapbase - obj->vaddrbase);
        !           318:                                obj->textsize = round_up(vaddr + ph->p_memsz) -
        !           319:                                    obj->vaddrbase;
1.4       christos  320:                        } else {                /* Last load segment */
1.24    ! christos  321:                                obj->mapsize = round_up(vaddr + ph->p_memsz) -
        !           322:                                    obj->vaddrbase;
1.4       christos  323:                        }
                    324:                        ++nsegs;
                    325:                        break;
                    326:
1.5       kleink    327:                case PT_DYNAMIC:
1.24    ! christos  328:                        obj->dynamic = (Elf_Dyn *)vaddr;
1.4       christos  329:                        break;
                    330:                }
1.1       cgd       331:        }
1.4       christos  332:        assert(nsegs == 2);
1.1       cgd       333:
1.4       christos  334:        obj->entry = entry;
                    335:        return obj;
1.1       cgd       336: }

CVSweb <webmaster@jp.NetBSD.org>