Home | History | Annotate | Line # | Download | only in ld.elf_so
headers.c revision 1.3
      1  1.3  christos /*	$NetBSD: headers.c,v 1.3 1999/02/24 18:31:00 christos Exp $	*/
      2  1.1       cgd 
      3  1.1       cgd /*
      4  1.1       cgd  * Copyright 1996 John D. Polstra.
      5  1.1       cgd  * Copyright 1996 Matt Thomas <matt (at) 3am-software.com>
      6  1.1       cgd  * All rights reserved.
      7  1.1       cgd  *
      8  1.1       cgd  * Redistribution and use in source and binary forms, with or without
      9  1.1       cgd  * modification, are permitted provided that the following conditions
     10  1.1       cgd  * are met:
     11  1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     12  1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     13  1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     14  1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     15  1.1       cgd  *    documentation and/or other materials provided with the distribution.
     16  1.1       cgd  * 3. All advertising materials mentioning features or use of this software
     17  1.1       cgd  *    must display the following acknowledgement:
     18  1.1       cgd  *      This product includes software developed by John Polstra.
     19  1.1       cgd  * 4. The name of the author may not be used to endorse or promote products
     20  1.1       cgd  *    derived from this software without specific prior written permission.
     21  1.1       cgd  *
     22  1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     23  1.1       cgd  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24  1.1       cgd  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25  1.1       cgd  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     26  1.1       cgd  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     27  1.1       cgd  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28  1.1       cgd  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29  1.1       cgd  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30  1.1       cgd  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     31  1.1       cgd  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32  1.1       cgd  */
     33  1.1       cgd 
     34  1.1       cgd /*
     35  1.1       cgd  * Dynamic linker for ELF.
     36  1.1       cgd  *
     37  1.1       cgd  * John Polstra <jdp (at) polstra.com>.
     38  1.1       cgd  */
     39  1.1       cgd 
     40  1.1       cgd #include <err.h>
     41  1.1       cgd #include <errno.h>
     42  1.1       cgd #include <fcntl.h>
     43  1.1       cgd #include <stdarg.h>
     44  1.1       cgd #include <stdio.h>
     45  1.1       cgd #include <stdlib.h>
     46  1.1       cgd #include <string.h>
     47  1.1       cgd #include <unistd.h>
     48  1.1       cgd #include <sys/types.h>
     49  1.1       cgd #include <sys/mman.h>
     50  1.1       cgd #include <dirent.h>
     51  1.1       cgd 
     52  1.1       cgd #include "debug.h"
     53  1.1       cgd #include "rtld.h"
     54  1.1       cgd 
     55  1.1       cgd /*
     56  1.1       cgd  * Process a shared object's DYNAMIC section, and save the important
     57  1.1       cgd  * information in its Obj_Entry structure.
     58  1.1       cgd  */
     59  1.1       cgd void
     60  1.1       cgd _rtld_digest_dynamic(
     61  1.1       cgd     Obj_Entry *obj)
     62  1.1       cgd {
     63  1.1       cgd     Elf_Dyn *dynp;
     64  1.1       cgd     Needed_Entry **needed_tail = &obj->needed;
     65  1.1       cgd     const Elf_Dyn *dyn_rpath = NULL;
     66  1.1       cgd     enum Elf_e_dynamic_type plttype = Elf_edt_rel;
     67  1.1       cgd     Elf_Word relsize = 0, relasize = 0, pltrelsize = 0, pltrelasize = 0;
     68  1.1       cgd 
     69  1.1       cgd     for (dynp = obj->dynamic;  dynp->d_tag != Elf_edt_null;  ++dynp) {
     70  1.1       cgd 	switch(dynp->d_tag) {
     71  1.1       cgd 
     72  1.1       cgd 	case Elf_edt_rel:
     73  1.1       cgd 	    obj->rel = (const Elf_Rel *) (obj->relocbase + dynp->d_un.d_ptr);
     74  1.1       cgd 	    break;
     75  1.1       cgd 
     76  1.1       cgd 	case Elf_edt_relsz:
     77  1.1       cgd 	    relsize = dynp->d_un.d_val;
     78  1.1       cgd 	    break;
     79  1.1       cgd 
     80  1.1       cgd 	case Elf_edt_relent:
     81  1.1       cgd 	    assert(dynp->d_un.d_val == sizeof(Elf_Rel));
     82  1.1       cgd 	    break;
     83  1.1       cgd 
     84  1.1       cgd 	case Elf_edt_jmprel:
     85  1.1       cgd 	    if (plttype == Elf_edt_rel) {
     86  1.1       cgd 		obj->pltrel = (const Elf_Rel *)
     87  1.1       cgd 		    (obj->relocbase + dynp->d_un.d_ptr);
     88  1.1       cgd 	    } else {
     89  1.1       cgd 		obj->pltrela = (const Elf_RelA *)
     90  1.1       cgd 		    (obj->relocbase + dynp->d_un.d_ptr);
     91  1.1       cgd 	    }
     92  1.1       cgd 	    break;
     93  1.1       cgd 
     94  1.1       cgd 	case Elf_edt_pltrelsz:
     95  1.1       cgd 	    if (plttype == Elf_edt_rel) {
     96  1.1       cgd 		pltrelsize = dynp->d_un.d_val;
     97  1.1       cgd 	    } else {
     98  1.1       cgd 		pltrelasize = dynp->d_un.d_val;
     99  1.1       cgd 	    }
    100  1.1       cgd 	    break;
    101  1.1       cgd 
    102  1.1       cgd 	case Elf_edt_rela:
    103  1.1       cgd 	    obj->rela = (const Elf_RelA *) (obj->relocbase + dynp->d_un.d_ptr);
    104  1.1       cgd 	    break;
    105  1.1       cgd 
    106  1.1       cgd 	case Elf_edt_relasz:
    107  1.1       cgd 	    relasize = dynp->d_un.d_val;
    108  1.1       cgd 	    break;
    109  1.1       cgd 
    110  1.1       cgd 	case Elf_edt_relaent:
    111  1.1       cgd 	    assert(dynp->d_un.d_val == sizeof(Elf_RelA));
    112  1.1       cgd 	    break;
    113  1.1       cgd 
    114  1.1       cgd 	case Elf_edt_pltrel:
    115  1.1       cgd 	    plttype = dynp->d_un.d_val;
    116  1.1       cgd 	    assert(plttype == Elf_edt_rel || plttype == Elf_edt_rela);
    117  1.1       cgd 	    if (plttype == Elf_edt_rela) {
    118  1.1       cgd 		obj->pltrela = (const Elf_RelA *) obj->pltrel;
    119  1.1       cgd 		obj->pltrel = NULL;
    120  1.1       cgd 		pltrelasize = pltrelsize;
    121  1.1       cgd 		pltrelsize = 0;
    122  1.1       cgd 	    }
    123  1.1       cgd 	    break;
    124  1.1       cgd 
    125  1.1       cgd 	case Elf_edt_symtab:
    126  1.1       cgd 	    obj->symtab = (const Elf_Sym *)
    127  1.1       cgd 		(obj->relocbase + dynp->d_un.d_ptr);
    128  1.1       cgd 	    break;
    129  1.1       cgd 
    130  1.1       cgd 	case Elf_edt_syment:
    131  1.1       cgd 	    assert(dynp->d_un.d_val == sizeof(Elf_Sym));
    132  1.1       cgd 	    break;
    133  1.1       cgd 
    134  1.1       cgd 	case Elf_edt_strtab:
    135  1.1       cgd 	    obj->strtab = (const char *) (obj->relocbase + dynp->d_un.d_ptr);
    136  1.1       cgd 	    break;
    137  1.1       cgd 
    138  1.1       cgd 	case Elf_edt_strsz:
    139  1.1       cgd 	    obj->strsize = dynp->d_un.d_val;
    140  1.1       cgd 	    break;
    141  1.1       cgd 
    142  1.1       cgd 	case Elf_edt_hash:
    143  1.1       cgd 	    {
    144  1.1       cgd 		const Elf_Word *hashtab = (const Elf_Word *)
    145  1.1       cgd 		    (obj->relocbase + dynp->d_un.d_ptr);
    146  1.1       cgd 		obj->nbuckets = hashtab[0];
    147  1.1       cgd 		obj->nchains = hashtab[1];
    148  1.1       cgd 		obj->buckets = hashtab + 2;
    149  1.1       cgd 		obj->chains = obj->buckets + obj->nbuckets;
    150  1.1       cgd 	    }
    151  1.1       cgd 	    break;
    152  1.1       cgd 
    153  1.1       cgd 	case Elf_edt_needed:
    154  1.1       cgd 	    assert(!obj->rtld);
    155  1.1       cgd 	    {
    156  1.1       cgd 		Needed_Entry *nep = NEW(Needed_Entry);
    157  1.1       cgd 		nep->name = dynp->d_un.d_val;
    158  1.1       cgd 		nep->obj = NULL;
    159  1.1       cgd 		nep->next = NULL;
    160  1.1       cgd 
    161  1.1       cgd 		*needed_tail = nep;
    162  1.1       cgd 		needed_tail = &nep->next;
    163  1.1       cgd 	    }
    164  1.1       cgd 	    break;
    165  1.1       cgd 
    166  1.1       cgd 	case Elf_edt_pltgot:
    167  1.1       cgd 	    obj->pltgot = (Elf_Addr *) (obj->relocbase + dynp->d_un.d_ptr);
    168  1.1       cgd 	    break;
    169  1.1       cgd 
    170  1.1       cgd 	case Elf_edt_textrel:
    171  1.1       cgd 	    obj->textrel = true;
    172  1.1       cgd 	    break;
    173  1.1       cgd 
    174  1.1       cgd 	case Elf_edt_symbolic:
    175  1.1       cgd 	    obj->symbolic = true;
    176  1.1       cgd 	    break;
    177  1.1       cgd 
    178  1.1       cgd 	case Elf_edt_rpath:
    179  1.1       cgd 	    /*
    180  1.1       cgd 	     * We have to wait until later to process this, because we
    181  1.1       cgd 	     * might not have gotten the address of the string table yet.
    182  1.1       cgd 	     */
    183  1.1       cgd 	    dyn_rpath = dynp;
    184  1.1       cgd 	    break;
    185  1.1       cgd 
    186  1.1       cgd 	case Elf_edt_soname:
    187  1.1       cgd 	    /* Not used by the dynamic linker. */
    188  1.1       cgd 	    break;
    189  1.1       cgd 
    190  1.1       cgd 	case Elf_edt_init:
    191  1.1       cgd 	    obj->init = (void (*)(void)) (obj->relocbase + dynp->d_un.d_ptr);
    192  1.1       cgd 	    break;
    193  1.1       cgd 
    194  1.1       cgd 	case Elf_edt_fini:
    195  1.1       cgd 	    obj->fini = (void (*)(void)) (obj->relocbase + dynp->d_un.d_ptr);
    196  1.1       cgd 	    break;
    197  1.1       cgd 
    198  1.1       cgd 	case Elf_edt_debug:
    199  1.1       cgd #ifdef RTLD_LOADER
    200  1.1       cgd 	    dynp->d_un.d_ptr = (Elf_Addr) &_rtld_debug;
    201  1.1       cgd #endif
    202  1.1       cgd 	    break;
    203  1.2    mhitch 
    204  1.2    mhitch #if defined(__mips__)
    205  1.2    mhitch 	case DT_MIPS_LOCAL_GOTNO:
    206  1.2    mhitch 	    obj->local_gotno = dynp->d_un.d_val;
    207  1.2    mhitch 	    break;
    208  1.2    mhitch 
    209  1.2    mhitch 	case DT_MIPS_SYMTABNO:
    210  1.2    mhitch 	    obj->symtabno = dynp->d_un.d_val;
    211  1.2    mhitch 	    break;
    212  1.2    mhitch 
    213  1.2    mhitch 	case DT_MIPS_GOTSYM:
    214  1.2    mhitch 	    obj->gotsym = dynp->d_un.d_val;
    215  1.2    mhitch 	    break;
    216  1.2    mhitch 
    217  1.2    mhitch 	case DT_MIPS_RLD_MAP:
    218  1.2    mhitch #ifdef RTLD_LOADER
    219  1.2    mhitch 	    *((Elf_Addr *)(dynp->d_un.d_ptr)) = (Elf_Addr) &_rtld_debug;
    220  1.2    mhitch #endif
    221  1.2    mhitch 	    break;
    222  1.2    mhitch #endif
    223  1.1       cgd 	}
    224  1.1       cgd     }
    225  1.1       cgd 
    226  1.1       cgd     obj->rellim     = (const Elf_Rel  *) ((caddr_t) obj->rel     + relsize);
    227  1.1       cgd     obj->relalim    = (const Elf_RelA *) ((caddr_t) obj->rela    + relasize);
    228  1.1       cgd     obj->pltrellim  = (const Elf_Rel  *) ((caddr_t) obj->pltrel  + pltrelsize);
    229  1.1       cgd     obj->pltrelalim = (const Elf_RelA *) ((caddr_t) obj->pltrela + pltrelasize);
    230  1.1       cgd 
    231  1.1       cgd     if (dyn_rpath != NULL) {
    232  1.3  christos 	_rtld_add_paths(&obj->rpaths, obj->strtab + dyn_rpath->d_un.d_val,
    233  1.3  christos 	    true);
    234  1.1       cgd     }
    235  1.1       cgd }
    236  1.1       cgd 
    237  1.1       cgd /*
    238  1.1       cgd  * Process a shared object's program header.  This is used only for the
    239  1.1       cgd  * main program, when the kernel has already loaded the main program
    240  1.1       cgd  * into memory before calling the dynamic linker.  It creates and
    241  1.1       cgd  * returns an Obj_Entry structure.
    242  1.1       cgd  */
    243  1.1       cgd Obj_Entry *
    244  1.1       cgd _rtld_digest_phdr(
    245  1.1       cgd     const Elf_Phdr *phdr,
    246  1.1       cgd     int phnum,
    247  1.1       cgd     caddr_t entry)
    248  1.1       cgd {
    249  1.1       cgd     Obj_Entry *obj = CNEW(Obj_Entry);
    250  1.1       cgd     const Elf_Phdr *phlimit = phdr + phnum;
    251  1.1       cgd     const Elf_Phdr *ph;
    252  1.1       cgd     int nsegs = 0;
    253  1.1       cgd 
    254  1.1       cgd     for (ph = phdr;  ph < phlimit;  ++ph) {
    255  1.1       cgd 	switch(ph->p_type) {
    256  1.1       cgd 
    257  1.1       cgd 	case Elf_pt_phdr:
    258  1.1       cgd 	    assert((const Elf_Phdr *) ph->p_vaddr == phdr);
    259  1.1       cgd 	    obj->phdr = (const Elf_Phdr *) ph->p_vaddr;
    260  1.1       cgd 	    obj->phsize = ph->p_memsz;
    261  1.1       cgd 	    break;
    262  1.1       cgd 
    263  1.1       cgd 	case Elf_pt_load:
    264  1.1       cgd 	    assert(nsegs < 2);
    265  1.1       cgd 	    if (nsegs == 0) {	/* First load segment */
    266  1.1       cgd 		obj->vaddrbase = round_down(ph->p_vaddr);
    267  1.1       cgd 		obj->mapbase = (caddr_t) obj->vaddrbase;
    268  1.1       cgd 		obj->relocbase = obj->mapbase - obj->vaddrbase;
    269  1.1       cgd 		obj->textsize = round_up(ph->p_vaddr + ph->p_memsz) -
    270  1.1       cgd 		    obj->vaddrbase;
    271  1.1       cgd 	    } else {		/* Last load segment */
    272  1.1       cgd 		obj->mapsize = round_up(ph->p_vaddr + ph->p_memsz) -
    273  1.1       cgd 		    obj->vaddrbase;
    274  1.1       cgd 	    }
    275  1.1       cgd 	    ++nsegs;
    276  1.1       cgd 	    break;
    277  1.1       cgd 
    278  1.1       cgd 	case Elf_pt_dynamic:
    279  1.1       cgd 	    obj->dynamic = (Elf_Dyn *) ph->p_vaddr;
    280  1.1       cgd 	    break;
    281  1.1       cgd 	}
    282  1.1       cgd     }
    283  1.1       cgd     assert(nsegs == 2);
    284  1.1       cgd 
    285  1.1       cgd     obj->entry = entry;
    286  1.1       cgd     return obj;
    287  1.1       cgd }
    288