1 /* $NetBSD: headers.c,v 1.1 1996/12/16 20:37:58 cgd Exp $ */ 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 55 /* 56 * Process a shared object's DYNAMIC section, and save the important 57 * information in its Obj_Entry structure. 58 */ 59 void 60 _rtld_digest_dynamic( 61 Obj_Entry *obj) 62 { 63 Elf_Dyn *dynp; 64 Needed_Entry **needed_tail = &obj->needed; 65 const Elf_Dyn *dyn_rpath = NULL; 66 enum Elf_e_dynamic_type plttype = Elf_edt_rel; 67 Elf_Word relsize = 0, relasize = 0, pltrelsize = 0, pltrelasize = 0; 68 69 for (dynp = obj->dynamic; dynp->d_tag != Elf_edt_null; ++dynp) { 70 switch(dynp->d_tag) { 71 72 case Elf_edt_rel: 73 obj->rel = (const Elf_Rel *) (obj->relocbase + dynp->d_un.d_ptr); 74 break; 75 76 case Elf_edt_relsz: 77 relsize = dynp->d_un.d_val; 78 break; 79 80 case Elf_edt_relent: 81 assert(dynp->d_un.d_val == sizeof(Elf_Rel)); 82 break; 83 84 case Elf_edt_jmprel: 85 if (plttype == Elf_edt_rel) { 86 obj->pltrel = (const Elf_Rel *) 87 (obj->relocbase + dynp->d_un.d_ptr); 88 } else { 89 obj->pltrela = (const Elf_RelA *) 90 (obj->relocbase + dynp->d_un.d_ptr); 91 } 92 break; 93 94 case Elf_edt_pltrelsz: 95 if (plttype == Elf_edt_rel) { 96 pltrelsize = dynp->d_un.d_val; 97 } else { 98 pltrelasize = dynp->d_un.d_val; 99 } 100 break; 101 102 case Elf_edt_rela: 103 obj->rela = (const Elf_RelA *) (obj->relocbase + dynp->d_un.d_ptr); 104 break; 105 106 case Elf_edt_relasz: 107 relasize = dynp->d_un.d_val; 108 break; 109 110 case Elf_edt_relaent: 111 assert(dynp->d_un.d_val == sizeof(Elf_RelA)); 112 break; 113 114 case Elf_edt_pltrel: 115 plttype = dynp->d_un.d_val; 116 assert(plttype == Elf_edt_rel || plttype == Elf_edt_rela); 117 if (plttype == Elf_edt_rela) { 118 obj->pltrela = (const Elf_RelA *) obj->pltrel; 119 obj->pltrel = NULL; 120 pltrelasize = pltrelsize; 121 pltrelsize = 0; 122 } 123 break; 124 125 case Elf_edt_symtab: 126 obj->symtab = (const Elf_Sym *) 127 (obj->relocbase + dynp->d_un.d_ptr); 128 break; 129 130 case Elf_edt_syment: 131 assert(dynp->d_un.d_val == sizeof(Elf_Sym)); 132 break; 133 134 case Elf_edt_strtab: 135 obj->strtab = (const char *) (obj->relocbase + dynp->d_un.d_ptr); 136 break; 137 138 case Elf_edt_strsz: 139 obj->strsize = dynp->d_un.d_val; 140 break; 141 142 case Elf_edt_hash: 143 { 144 const Elf_Word *hashtab = (const Elf_Word *) 145 (obj->relocbase + dynp->d_un.d_ptr); 146 obj->nbuckets = hashtab[0]; 147 obj->nchains = hashtab[1]; 148 obj->buckets = hashtab + 2; 149 obj->chains = obj->buckets + obj->nbuckets; 150 } 151 break; 152 153 case Elf_edt_needed: 154 assert(!obj->rtld); 155 { 156 Needed_Entry *nep = NEW(Needed_Entry); 157 nep->name = dynp->d_un.d_val; 158 nep->obj = NULL; 159 nep->next = NULL; 160 161 *needed_tail = nep; 162 needed_tail = &nep->next; 163 } 164 break; 165 166 case Elf_edt_pltgot: 167 obj->pltgot = (Elf_Addr *) (obj->relocbase + dynp->d_un.d_ptr); 168 break; 169 170 case Elf_edt_textrel: 171 obj->textrel = true; 172 break; 173 174 case Elf_edt_symbolic: 175 obj->symbolic = true; 176 break; 177 178 case Elf_edt_rpath: 179 /* 180 * We have to wait until later to process this, because we 181 * might not have gotten the address of the string table yet. 182 */ 183 dyn_rpath = dynp; 184 break; 185 186 case Elf_edt_soname: 187 /* Not used by the dynamic linker. */ 188 break; 189 190 case Elf_edt_init: 191 obj->init = (void (*)(void)) (obj->relocbase + dynp->d_un.d_ptr); 192 break; 193 194 case Elf_edt_fini: 195 obj->fini = (void (*)(void)) (obj->relocbase + dynp->d_un.d_ptr); 196 break; 197 198 case Elf_edt_debug: 199 #ifdef RTLD_LOADER 200 dynp->d_un.d_ptr = (Elf_Addr) &_rtld_debug; 201 #endif 202 break; 203 } 204 } 205 206 obj->rellim = (const Elf_Rel *) ((caddr_t) obj->rel + relsize); 207 obj->relalim = (const Elf_RelA *) ((caddr_t) obj->rela + relasize); 208 obj->pltrellim = (const Elf_Rel *) ((caddr_t) obj->pltrel + pltrelsize); 209 obj->pltrelalim = (const Elf_RelA *) ((caddr_t) obj->pltrela + pltrelasize); 210 211 if (dyn_rpath != NULL) { 212 _rtld_add_paths(&obj->rpaths, obj->strtab + dyn_rpath->d_un.d_val); 213 } 214 } 215 216 /* 217 * Process a shared object's program header. This is used only for the 218 * main program, when the kernel has already loaded the main program 219 * into memory before calling the dynamic linker. It creates and 220 * returns an Obj_Entry structure. 221 */ 222 Obj_Entry * 223 _rtld_digest_phdr( 224 const Elf_Phdr *phdr, 225 int phnum, 226 caddr_t entry) 227 { 228 Obj_Entry *obj = CNEW(Obj_Entry); 229 const Elf_Phdr *phlimit = phdr + phnum; 230 const Elf_Phdr *ph; 231 int nsegs = 0; 232 233 for (ph = phdr; ph < phlimit; ++ph) { 234 switch(ph->p_type) { 235 236 case Elf_pt_phdr: 237 assert((const Elf_Phdr *) ph->p_vaddr == phdr); 238 obj->phdr = (const Elf_Phdr *) ph->p_vaddr; 239 obj->phsize = ph->p_memsz; 240 break; 241 242 case Elf_pt_load: 243 assert(nsegs < 2); 244 if (nsegs == 0) { /* First load segment */ 245 obj->vaddrbase = round_down(ph->p_vaddr); 246 obj->mapbase = (caddr_t) obj->vaddrbase; 247 obj->relocbase = obj->mapbase - obj->vaddrbase; 248 obj->textsize = round_up(ph->p_vaddr + ph->p_memsz) - 249 obj->vaddrbase; 250 } else { /* Last load segment */ 251 obj->mapsize = round_up(ph->p_vaddr + ph->p_memsz) - 252 obj->vaddrbase; 253 } 254 ++nsegs; 255 break; 256 257 case Elf_pt_dynamic: 258 obj->dynamic = (Elf_Dyn *) ph->p_vaddr; 259 break; 260 } 261 } 262 assert(nsegs == 2); 263 264 obj->entry = entry; 265 return obj; 266 } 267