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

1.60    ! joerg       1: /*     $NetBSD: headers.c,v 1.59 2014/08/26 21:20:05 joerg 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.60    ! joerg      43: __RCSID("$NetBSD: headers.c,v 1.59 2014/08/26 21:20:05 joerg 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>
1.29      joerg      56: #include <sys/bitops.h>
1.1       cgd        57: #include <dirent.h>
                     58:
                     59: #include "debug.h"
                     60: #include "rtld.h"
                     61:
                     62: /*
                     63:  * Process a shared object's DYNAMIC section, and save the important
                     64:  * information in its Obj_Entry structure.
                     65:  */
                     66: void
1.22      christos   67: _rtld_digest_dynamic(const char *execname, Obj_Entry *obj)
1.1       cgd        68: {
1.4       christos   69:        Elf_Dyn        *dynp;
                     70:        Needed_Entry  **needed_tail = &obj->needed;
1.51      christos   71:        const Elf_Dyn  *dyn_soname = NULL;
1.4       christos   72:        const Elf_Dyn  *dyn_rpath = NULL;
1.30      joerg      73:        bool            use_pltrel = false;
                     74:        bool            use_pltrela = false;
1.8       mycroft    75:        Elf_Addr        relsz = 0, relasz = 0;
1.13      mycroft    76:        Elf_Addr        pltrel = 0, pltrelsz = 0;
1.58      christos   77: #ifdef RTLD_LOADER
1.10      fredette   78:        Elf_Addr        init = 0, fini = 0;
1.58      christos   79: #endif
1.4       christos   80:
1.49      skrll      81:        dbg(("headers: digesting PT_DYNAMIC at %p", obj->dynamic));
1.5       kleink     82:        for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; ++dynp) {
1.49      skrll      83:                dbg(("  d_tag %ld at %p", (long)dynp->d_tag, dynp));
1.4       christos   84:                switch (dynp->d_tag) {
                     85:
1.5       kleink     86:                case DT_REL:
1.4       christos   87:                        obj->rel = (const Elf_Rel *)
                     88:                            (obj->relocbase + dynp->d_un.d_ptr);
                     89:                        break;
                     90:
1.5       kleink     91:                case DT_RELSZ:
1.4       christos   92:                        relsz = dynp->d_un.d_val;
                     93:                        break;
                     94:
1.5       kleink     95:                case DT_RELENT:
1.4       christos   96:                        assert(dynp->d_un.d_val == sizeof(Elf_Rel));
                     97:                        break;
                     98:
1.5       kleink     99:                case DT_JMPREL:
1.13      mycroft   100:                        pltrel = dynp->d_un.d_ptr;
1.4       christos  101:                        break;
                    102:
1.5       kleink    103:                case DT_PLTRELSZ:
1.8       mycroft   104:                        pltrelsz = dynp->d_un.d_val;
1.4       christos  105:                        break;
                    106:
1.5       kleink    107:                case DT_RELA:
1.9       kleink    108:                        obj->rela = (const Elf_Rela *)
1.4       christos  109:                            (obj->relocbase + dynp->d_un.d_ptr);
                    110:                        break;
                    111:
1.5       kleink    112:                case DT_RELASZ:
1.4       christos  113:                        relasz = dynp->d_un.d_val;
                    114:                        break;
                    115:
1.5       kleink    116:                case DT_RELAENT:
1.9       kleink    117:                        assert(dynp->d_un.d_val == sizeof(Elf_Rela));
1.4       christos  118:                        break;
                    119:
1.5       kleink    120:                case DT_PLTREL:
1.30      joerg     121:                        use_pltrel = dynp->d_un.d_val == DT_REL;
                    122:                        use_pltrela = dynp->d_un.d_val == DT_RELA;
                    123:                        assert(use_pltrel || use_pltrela);
1.4       christos  124:                        break;
                    125:
1.5       kleink    126:                case DT_SYMTAB:
1.4       christos  127:                        obj->symtab = (const Elf_Sym *)
                    128:                                (obj->relocbase + dynp->d_un.d_ptr);
                    129:                        break;
                    130:
1.5       kleink    131:                case DT_SYMENT:
1.4       christos  132:                        assert(dynp->d_un.d_val == sizeof(Elf_Sym));
                    133:                        break;
                    134:
1.5       kleink    135:                case DT_STRTAB:
1.4       christos  136:                        obj->strtab = (const char *)
                    137:                            (obj->relocbase + dynp->d_un.d_ptr);
                    138:                        break;
                    139:
1.5       kleink    140:                case DT_STRSZ:
1.4       christos  141:                        obj->strsize = dynp->d_un.d_val;
                    142:                        break;
                    143:
1.41      nonaka    144:                case DT_VERNEED:
                    145:                        obj->verneed = (const Elf_Verneed *)
                    146:                            (obj->relocbase + dynp->d_un.d_ptr);
                    147:                        break;
                    148:
                    149:                case DT_VERNEEDNUM:
                    150:                        obj->verneednum = dynp->d_un.d_val;
                    151:                        break;
                    152:
                    153:                case DT_VERDEF:
                    154:                        obj->verdef = (const Elf_Verdef *)
                    155:                            (obj->relocbase + dynp->d_un.d_ptr);
                    156:                        break;
                    157:
                    158:                case DT_VERDEFNUM:
                    159:                        obj->verdefnum = dynp->d_un.d_val;
                    160:                        break;
                    161:
                    162:                case DT_VERSYM:
                    163:                        obj->versyms = (const Elf_Versym *)
                    164:                            (obj->relocbase + dynp->d_un.d_ptr);
                    165:                        break;
                    166:
1.5       kleink    167:                case DT_HASH:
1.4       christos  168:                        {
1.31      skrll     169:                                const Elf_Symindx *hashtab = (const Elf_Symindx *)
                    170:                                    (obj->relocbase + dynp->d_un.d_ptr);
1.4       christos  171:
1.29      joerg     172:                                if (hashtab[0] > UINT32_MAX)
                    173:                                        obj->nbuckets = UINT32_MAX;
                    174:                                else
                    175:                                        obj->nbuckets = hashtab[0];
1.4       christos  176:                                obj->nchains = hashtab[1];
                    177:                                obj->buckets = hashtab + 2;
                    178:                                obj->chains = obj->buckets + obj->nbuckets;
1.29      joerg     179:                                /*
                    180:                                 * Should really be in _rtld_relocate_objects,
                    181:                                 * but _rtld_symlook_obj might be used before.
                    182:                                 */
                    183:                                if (obj->nbuckets) {
                    184:                                        fast_divide32_prepare(obj->nbuckets,
                    185:                                            &obj->nbuckets_m,
                    186:                                            &obj->nbuckets_s1,
                    187:                                            &obj->nbuckets_s2);
                    188:                                }
1.4       christos  189:                        }
                    190:                        break;
                    191:
1.5       kleink    192:                case DT_NEEDED:
1.4       christos  193:                        {
                    194:                                Needed_Entry *nep = NEW(Needed_Entry);
                    195:
                    196:                                nep->name = dynp->d_un.d_val;
                    197:                                nep->obj = NULL;
                    198:                                nep->next = NULL;
                    199:
                    200:                                *needed_tail = nep;
                    201:                                needed_tail = &nep->next;
                    202:                        }
                    203:                        break;
                    204:
1.5       kleink    205:                case DT_PLTGOT:
1.4       christos  206:                        obj->pltgot = (Elf_Addr *)
                    207:                            (obj->relocbase + dynp->d_un.d_ptr);
                    208:                        break;
                    209:
1.5       kleink    210:                case DT_TEXTREL:
1.4       christos  211:                        obj->textrel = true;
                    212:                        break;
                    213:
1.5       kleink    214:                case DT_SYMBOLIC:
1.4       christos  215:                        obj->symbolic = true;
                    216:                        break;
                    217:
1.5       kleink    218:                case DT_RPATH:
1.4       christos  219:                        /*
                    220:                         * We have to wait until later to process this, because
                    221:                         * we might not have gotten the address of the string
                    222:                         * table yet.
                    223:                         */
                    224:                        dyn_rpath = dynp;
                    225:                        break;
                    226:
1.5       kleink    227:                case DT_SONAME:
1.51      christos  228:                        dyn_soname = dynp;
1.4       christos  229:                        break;
                    230:
1.5       kleink    231:                case DT_INIT:
1.58      christos  232: #ifdef RTLD_LOADER
1.10      fredette  233:                        init = dynp->d_un.d_ptr;
1.58      christos  234: #endif
1.4       christos  235:                        break;
                    236:
1.43      matt      237: #ifdef HAVE_INITFINI_ARRAY
                    238:                case DT_INIT_ARRAY:
1.59      joerg     239:                        obj->init_array =
                    240:                            (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr);
1.49      skrll     241:                        dbg(("headers: DT_INIT_ARRAY at %p",
                    242:                            obj->init_array));
1.43      matt      243:                        break;
                    244:
                    245:                case DT_INIT_ARRAYSZ:
                    246:                        obj->init_arraysz = dynp->d_un.d_val / sizeof(fptr_t);
1.49      skrll     247:                        dbg(("headers: DT_INIT_ARRAYZ %zu",
                    248:                            obj->init_arraysz));
1.43      matt      249:                        break;
                    250: #endif
                    251:
1.5       kleink    252:                case DT_FINI:
1.58      christos  253: #ifdef RTLD_LOADER
1.10      fredette  254:                        fini = dynp->d_un.d_ptr;
1.58      christos  255: #endif
1.4       christos  256:                        break;
1.1       cgd       257:
1.43      matt      258: #ifdef HAVE_INITFINI_ARRAY
                    259:                case DT_FINI_ARRAY:
                    260:                        obj->fini_array =
1.55      joerg     261:                            (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr);
1.49      skrll     262:                        dbg(("headers: DT_FINI_ARRAY at %p",
                    263:                            obj->fini_array));
1.43      matt      264:                        break;
                    265:
                    266:                case DT_FINI_ARRAYSZ:
1.50      skrll     267:                        obj->fini_arraysz = dynp->d_un.d_val / sizeof(fptr_t);
1.49      skrll     268:                        dbg(("headers: DT_FINI_ARRAYZ %zu",
                    269:                            obj->fini_arraysz));
1.43      matt      270:                        break;
                    271: #endif
                    272:
1.20      simonb    273:                /*
                    274:                 * Don't process DT_DEBUG on MIPS as the dynamic section
                    275:                 * is mapped read-only. DT_MIPS_RLD_MAP is used instead.
                    276:                 * XXX: n32/n64 may use DT_DEBUG, not sure yet.
                    277:                 */
                    278: #ifndef __mips__
1.5       kleink    279:                case DT_DEBUG:
1.1       cgd       280: #ifdef RTLD_LOADER
1.4       christos  281:                        dynp->d_un.d_ptr = (Elf_Addr)&_rtld_debug;
1.1       cgd       282: #endif
1.4       christos  283:                        break;
1.20      simonb    284: #endif
1.2       mhitch    285:
1.14      mycroft   286: #ifdef __mips__
1.4       christos  287:                case DT_MIPS_LOCAL_GOTNO:
                    288:                        obj->local_gotno = dynp->d_un.d_val;
                    289:                        break;
                    290:
                    291:                case DT_MIPS_SYMTABNO:
                    292:                        obj->symtabno = dynp->d_un.d_val;
                    293:                        break;
                    294:
                    295:                case DT_MIPS_GOTSYM:
                    296:                        obj->gotsym = dynp->d_un.d_val;
                    297:                        break;
1.2       mhitch    298:
1.4       christos  299:                case DT_MIPS_RLD_MAP:
1.2       mhitch    300: #ifdef RTLD_LOADER
1.4       christos  301:                        *((Elf_Addr *)(dynp->d_un.d_ptr)) = (Elf_Addr)
                    302:                            &_rtld_debug;
1.2       mhitch    303: #endif
1.4       christos  304:                        break;
1.2       mhitch    305: #endif
1.39      matt      306: #ifdef __powerpc__
1.53      matt      307: #ifdef _LP64
                    308:                case DT_PPC64_GLINK:
1.54      matt      309:                        obj->glink = (Elf_Addr)(uintptr_t)obj->relocbase + dynp->d_un.d_ptr;
1.53      matt      310:                        break;
                    311: #else
1.39      matt      312:                case DT_PPC_GOT:
                    313:                        obj->gotptr = (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr);
                    314:                        break;
                    315: #endif
1.53      matt      316: #endif
1.23      ad        317:                case DT_FLAGS_1:
1.38      skrll     318:                        obj->z_now =
                    319:                            ((dynp->d_un.d_val & DF_1_BIND_NOW) != 0);
                    320:                        obj->z_nodelete =
                    321:                            ((dynp->d_un.d_val & DF_1_NODELETE) != 0);
                    322:                        obj->z_initfirst =
1.23      ad        323:                            ((dynp->d_un.d_val & DF_1_INITFIRST) != 0);
1.38      skrll     324:                        obj->z_noopen =
                    325:                            ((dynp->d_un.d_val & DF_1_NOOPEN) != 0);
1.23      ad        326:                        break;
1.4       christos  327:                }
1.1       cgd       328:        }
                    329:
1.28      lukem     330:        obj->rellim = (const Elf_Rel *)((const uint8_t *)obj->rel + relsz);
                    331:        obj->relalim = (const Elf_Rela *)((const uint8_t *)obj->rela + relasz);
1.30      joerg     332:        if (use_pltrel) {
1.13      mycroft   333:                obj->pltrel = (const Elf_Rel *)(obj->relocbase + pltrel);
                    334:                obj->pltrellim = (const Elf_Rel *)(obj->relocbase + pltrel + pltrelsz);
                    335:                obj->pltrelalim = 0;
                    336:                /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL.
                    337:                   Trim rel(a)lim to save time later. */
                    338:                if (obj->rellim && obj->pltrel &&
                    339:                    obj->rellim > obj->pltrel &&
                    340:                    obj->rellim <= obj->pltrellim)
1.11      mycroft   341:                        obj->rellim = obj->pltrel;
1.30      joerg     342:        } else if (use_pltrela) {
1.13      mycroft   343:                obj->pltrela = (const Elf_Rela *)(obj->relocbase + pltrel);
                    344:                obj->pltrellim = 0;
                    345:                obj->pltrelalim = (const Elf_Rela *)(obj->relocbase + pltrel + pltrelsz);
                    346:                /* On PPC and SPARC, at least, REL(A)SZ may include JMPREL.
                    347:                   Trim rel(a)lim to save time later. */
                    348:                if (obj->relalim && obj->pltrela &&
                    349:                    obj->relalim > obj->pltrela &&
                    350:                    obj->relalim <= obj->pltrelalim)
1.11      mycroft   351:                        obj->relalim = obj->pltrela;
1.8       mycroft   352:        }
1.10      fredette  353:
1.57      joerg     354: #ifdef RTLD_LOADER
1.10      fredette  355:        if (init != 0)
1.57      joerg     356:                obj->init = (Elf_Addr) obj->relocbase + init;
1.10      fredette  357:        if (fini != 0)
1.57      joerg     358:                obj->fini = (Elf_Addr) obj->relocbase + fini;
                    359: #endif
1.4       christos  360:
                    361:        if (dyn_rpath != NULL) {
1.22      christos  362:                _rtld_add_paths(execname, &obj->rpaths, obj->strtab +
1.12      mycroft   363:                    dyn_rpath->d_un.d_val);
1.4       christos  364:        }
1.51      christos  365:        if (dyn_soname != NULL) {
                    366:                _rtld_object_add_name(obj, obj->strtab +
                    367:                    dyn_soname->d_un.d_val);
                    368:        }
1.1       cgd       369: }
                    370:
                    371: /*
                    372:  * Process a shared object's program header.  This is used only for the
                    373:  * main program, when the kernel has already loaded the main program
                    374:  * into memory before calling the dynamic linker.  It creates and
                    375:  * returns an Obj_Entry structure.
                    376:  */
                    377: Obj_Entry *
1.18      skrll     378: _rtld_digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry)
1.1       cgd       379: {
1.6       mycroft   380:        Obj_Entry      *obj;
1.4       christos  381:        const Elf_Phdr *phlimit = phdr + phnum;
                    382:        const Elf_Phdr *ph;
                    383:        int             nsegs = 0;
1.24      christos  384:        Elf_Addr        vaddr;
1.4       christos  385:
1.6       mycroft   386:        obj = _rtld_obj_new();
1.36      skrll     387:
                    388:        for (ph = phdr; ph < phlimit; ++ph) {
                    389:                if (ph->p_type != PT_PHDR)
                    390:                        continue;
1.50      skrll     391:
1.60    ! joerg     392:                obj->relocbase = (caddr_t)((uintptr_t)phdr - (uintptr_t)ph->p_vaddr);
        !           393:                obj->phdr = phdr; /* Equivalent to relocbase + p_vaddr. */
1.46      matt      394:                obj->phsize = ph->p_memsz;
1.49      skrll     395:                dbg(("headers: phdr %p (%p) phsize %zu relocbase %p",
                    396:                    obj->phdr, phdr, obj->phsize, obj->relocbase));
1.36      skrll     397:                break;
                    398:        }
1.50      skrll     399:
1.4       christos  400:        for (ph = phdr; ph < phlimit; ++ph) {
1.37      skrll     401:                vaddr = (Elf_Addr)(uintptr_t)(obj->relocbase + ph->p_vaddr);
1.4       christos  402:                switch (ph->p_type) {
                    403:
1.6       mycroft   404:                case PT_INTERP:
1.27      mrg       405:                        obj->interp = (const char *)(uintptr_t)vaddr;
1.52      skrll     406:                        dbg(("headers: %s %p phsize %" PRImemsz,
1.49      skrll     407:                            "PT_INTERP", (void *)(uintptr_t)vaddr,
                    408:                             ph->p_memsz));
1.4       christos  409:                        break;
                    410:
1.5       kleink    411:                case PT_LOAD:
1.4       christos  412:                        assert(nsegs < 2);
                    413:                        if (nsegs == 0) {       /* First load segment */
1.24      christos  414:                                obj->vaddrbase = round_down(vaddr);
1.27      mrg       415:                                obj->mapbase = (caddr_t)(uintptr_t)obj->vaddrbase;
1.24      christos  416:                                obj->textsize = round_up(vaddr + ph->p_memsz) -
                    417:                                    obj->vaddrbase;
1.4       christos  418:                        } else {                /* Last load segment */
1.24      christos  419:                                obj->mapsize = round_up(vaddr + ph->p_memsz) -
                    420:                                    obj->vaddrbase;
1.4       christos  421:                        }
                    422:                        ++nsegs;
1.52      skrll     423:                        dbg(("headers: %s %p phsize %" PRImemsz,
1.49      skrll     424:                            "PT_LOAD", (void *)(uintptr_t)vaddr,
                    425:                             ph->p_memsz));
1.4       christos  426:                        break;
                    427:
1.5       kleink    428:                case PT_DYNAMIC:
1.27      mrg       429:                        obj->dynamic = (Elf_Dyn *)(uintptr_t)vaddr;
1.52      skrll     430:                        dbg(("headers: %s %p phsize %" PRImemsz,
1.49      skrll     431:                            "PT_DYNAMIC", (void *)(uintptr_t)vaddr,
                    432:                             ph->p_memsz));
1.4       christos  433:                        break;
1.40      joerg     434:
                    435: #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
                    436:                case PT_TLS:
                    437:                        obj->tlsindex = 1;
                    438:                        obj->tlssize = ph->p_memsz;
                    439:                        obj->tlsalign = ph->p_align;
                    440:                        obj->tlsinitsize = ph->p_filesz;
                    441:                        obj->tlsinit = (void *)(uintptr_t)ph->p_vaddr;
1.52      skrll     442:                        dbg(("headers: %s %p phsize %" PRImemsz,
1.49      skrll     443:                            "PT_TLS", (void *)(uintptr_t)vaddr,
                    444:                             ph->p_memsz));
1.40      joerg     445:                        break;
                    446: #endif
1.44      matt      447: #ifdef __ARM_EABI__
                    448:                case PT_ARM_EXIDX:
                    449:                        obj->exidx_start = (void *)(uintptr_t)vaddr;
                    450:                        obj->exidx_sz = ph->p_memsz;
1.52      skrll     451:                        dbg(("headers: %s %p phsize %" PRImemsz,
1.49      skrll     452:                            "PT_ARM_EXIDX", (void *)(uintptr_t)vaddr,
                    453:                             ph->p_memsz));
1.44      matt      454:                        break;
                    455: #endif
1.4       christos  456:                }
1.1       cgd       457:        }
1.4       christos  458:        assert(nsegs == 2);
1.1       cgd       459:
1.4       christos  460:        obj->entry = entry;
                    461:        return obj;
1.1       cgd       462: }

CVSweb <webmaster@jp.NetBSD.org>