1 /* $NetBSD: headers.c,v 1.61 2016/06/14 13:06:41 christos Exp $ */ 2 3 /* 4 * Copyright 1996 John D. Polstra. 5 * Copyright 1996 Matt Thomas <matt@3am-software.com> 6 * Copyright 2002 Charles M. Hannum <root@ihack.net> 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 41 #include <sys/cdefs.h> 42 #ifndef lint 43 __RCSID("$NetBSD: headers.c,v 1.61 2016/06/14 13:06:41 christos Exp $"); 44 #endif /* not lint */ 45 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 <sys/bitops.h> 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 67 _rtld_digest_dynamic(const char *execname, Obj_Entry *obj) 68 { 69 Elf_Dyn *dynp; 70 Needed_Entry **needed_tail = &obj->needed; 71 const Elf_Dyn *dyn_soname = NULL; 72 const Elf_Dyn *dyn_rpath = NULL; 73 bool use_pltrel = false; 74 bool use_pltrela = false; 75 Elf_Addr relsz = 0, relasz = 0; 76 Elf_Addr pltrel = 0, pltrelsz = 0; 77 #ifdef RTLD_LOADER 78 Elf_Addr init = 0, fini = 0; 79 #endif 80 81 dbg(("headers: digesting PT_DYNAMIC at %p", obj->dynamic)); 82 for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; ++dynp) { 83 dbg((" d_tag %ld at %p", (long)dynp->d_tag, dynp)); 84 switch (dynp->d_tag) { 85 86 case DT_REL: 87 obj->rel = (const Elf_Rel *) 88 (obj->relocbase + dynp->d_un.d_ptr); 89 break; 90 91 case DT_RELSZ: 92 relsz = dynp->d_un.d_val; 93 break; 94 95 case DT_RELENT: 96 assert(dynp->d_un.d_val == sizeof(Elf_Rel)); 97 break; 98 99 case DT_JMPREL: 100 pltrel = dynp->d_un.d_ptr; 101 break; 102 103 case DT_PLTRELSZ: 104 pltrelsz = dynp->d_un.d_val; 105 break; 106 107 case DT_RELA: 108 obj->rela = (const Elf_Rela *) 109 (obj->relocbase + dynp->d_un.d_ptr); 110 break; 111 112 case DT_RELASZ: 113 relasz = dynp->d_un.d_val; 114 break; 115 116 case DT_RELAENT: 117 assert(dynp->d_un.d_val == sizeof(Elf_Rela)); 118 break; 119 120 case DT_PLTREL: 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); 124 break; 125 126 case DT_SYMTAB: 127 obj->symtab = (const Elf_Sym *) 128 (obj->relocbase + dynp->d_un.d_ptr); 129 break; 130 131 case DT_SYMENT: 132 assert(dynp->d_un.d_val == sizeof(Elf_Sym)); 133 break; 134 135 case DT_STRTAB: 136 obj->strtab = (const char *) 137 (obj->relocbase + dynp->d_un.d_ptr); 138 break; 139 140 case DT_STRSZ: 141 obj->strsize = dynp->d_un.d_val; 142 break; 143 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 167 case DT_HASH: 168 { 169 const Elf_Symindx *hashtab = (const Elf_Symindx *) 170 (obj->relocbase + dynp->d_un.d_ptr); 171 172 if (hashtab[0] > UINT32_MAX) 173 obj->nbuckets = UINT32_MAX; 174 else 175 obj->nbuckets = hashtab[0]; 176 obj->nchains = hashtab[1]; 177 obj->buckets = hashtab + 2; 178 obj->chains = obj->buckets + obj->nbuckets; 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 } 189 } 190 break; 191 192 case DT_NEEDED: 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 205 case DT_PLTGOT: 206 obj->pltgot = (Elf_Addr *) 207 (obj->relocbase + dynp->d_un.d_ptr); 208 break; 209 210 case DT_TEXTREL: 211 obj->textrel = true; 212 break; 213 214 case DT_SYMBOLIC: 215 obj->symbolic = true; 216 break; 217 218 case DT_RPATH: 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 227 case DT_SONAME: 228 dyn_soname = dynp; 229 break; 230 231 case DT_INIT: 232 #ifdef RTLD_LOADER 233 init = dynp->d_un.d_ptr; 234 #endif 235 break; 236 237 #ifdef HAVE_INITFINI_ARRAY 238 case DT_INIT_ARRAY: 239 obj->init_array = 240 (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr); 241 dbg(("headers: DT_INIT_ARRAY at %p", 242 obj->init_array)); 243 break; 244 245 case DT_INIT_ARRAYSZ: 246 obj->init_arraysz = dynp->d_un.d_val / sizeof(fptr_t); 247 dbg(("headers: DT_INIT_ARRAYZ %zu", 248 obj->init_arraysz)); 249 break; 250 #endif 251 252 case DT_FINI: 253 #ifdef RTLD_LOADER 254 fini = dynp->d_un.d_ptr; 255 #endif 256 break; 257 258 #ifdef HAVE_INITFINI_ARRAY 259 case DT_FINI_ARRAY: 260 obj->fini_array = 261 (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr); 262 dbg(("headers: DT_FINI_ARRAY at %p", 263 obj->fini_array)); 264 break; 265 266 case DT_FINI_ARRAYSZ: 267 obj->fini_arraysz = dynp->d_un.d_val / sizeof(fptr_t); 268 dbg(("headers: DT_FINI_ARRAYZ %zu", 269 obj->fini_arraysz)); 270 break; 271 #endif 272 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__ 279 case DT_DEBUG: 280 #ifdef RTLD_LOADER 281 dynp->d_un.d_ptr = (Elf_Addr)&_rtld_debug; 282 #endif 283 break; 284 #endif 285 286 #ifdef __mips__ 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; 298 299 case DT_MIPS_RLD_MAP: 300 #ifdef RTLD_LOADER 301 *((Elf_Addr *)(dynp->d_un.d_ptr)) = (Elf_Addr) 302 &_rtld_debug; 303 #endif 304 break; 305 #endif 306 #ifdef __powerpc__ 307 #ifdef _LP64 308 case DT_PPC64_GLINK: 309 obj->glink = (Elf_Addr)(uintptr_t)obj->relocbase + dynp->d_un.d_ptr; 310 break; 311 #else 312 case DT_PPC_GOT: 313 obj->gotptr = (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr); 314 break; 315 #endif 316 #endif 317 case DT_FLAGS_1: 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 = 323 ((dynp->d_un.d_val & DF_1_INITFIRST) != 0); 324 obj->z_noopen = 325 ((dynp->d_un.d_val & DF_1_NOOPEN) != 0); 326 break; 327 } 328 } 329 330 obj->rellim = (const Elf_Rel *)((const uint8_t *)obj->rel + relsz); 331 obj->relalim = (const Elf_Rela *)((const uint8_t *)obj->rela + relasz); 332 if (use_pltrel) { 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) 341 obj->rellim = obj->pltrel; 342 } else if (use_pltrela) { 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) 351 obj->relalim = obj->pltrela; 352 } 353 354 #ifdef RTLD_LOADER 355 if (init != 0) 356 obj->init = (Elf_Addr) obj->relocbase + init; 357 if (fini != 0) 358 obj->fini = (Elf_Addr) obj->relocbase + fini; 359 #endif 360 361 if (dyn_rpath != NULL) { 362 _rtld_add_paths(execname, &obj->rpaths, obj->strtab + 363 dyn_rpath->d_un.d_val); 364 } 365 if (dyn_soname != NULL) { 366 _rtld_object_add_name(obj, obj->strtab + 367 dyn_soname->d_un.d_val); 368 } 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 * 378 _rtld_digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry) 379 { 380 Obj_Entry *obj; 381 const Elf_Phdr *phlimit = phdr + phnum; 382 const Elf_Phdr *ph; 383 int nsegs = 0; 384 Elf_Addr vaddr; 385 386 obj = _rtld_obj_new(); 387 388 for (ph = phdr; ph < phlimit; ++ph) { 389 if (ph->p_type != PT_PHDR) 390 continue; 391 392 obj->relocbase = (caddr_t)((uintptr_t)phdr - (uintptr_t)ph->p_vaddr); 393 obj->phdr = phdr; /* Equivalent to relocbase + p_vaddr. */ 394 obj->phsize = ph->p_memsz; 395 dbg(("headers: phdr %p (%p) phsize %zu relocbase %p", 396 obj->phdr, phdr, obj->phsize, obj->relocbase)); 397 break; 398 } 399 400 for (ph = phdr; ph < phlimit; ++ph) { 401 vaddr = (Elf_Addr)(uintptr_t)(obj->relocbase + ph->p_vaddr); 402 switch (ph->p_type) { 403 404 case PT_INTERP: 405 obj->interp = (const char *)(uintptr_t)vaddr; 406 dbg(("headers: %s %p phsize %" PRImemsz, 407 "PT_INTERP", (void *)(uintptr_t)vaddr, 408 ph->p_memsz)); 409 break; 410 411 case PT_LOAD: 412 assert(nsegs < 2); 413 if (nsegs == 0) { /* First load segment */ 414 obj->vaddrbase = round_down(vaddr); 415 obj->mapbase = (caddr_t)(uintptr_t)obj->vaddrbase; 416 obj->textsize = round_up(vaddr + ph->p_memsz) - 417 obj->vaddrbase; 418 } else { /* Last load segment */ 419 obj->mapsize = round_up(vaddr + ph->p_memsz) - 420 obj->vaddrbase; 421 } 422 ++nsegs; 423 dbg(("headers: %s %p phsize %" PRImemsz, 424 "PT_LOAD", (void *)(uintptr_t)vaddr, 425 ph->p_memsz)); 426 break; 427 428 case PT_DYNAMIC: 429 obj->dynamic = (Elf_Dyn *)(uintptr_t)vaddr; 430 dbg(("headers: %s %p phsize %" PRImemsz, 431 "PT_DYNAMIC", (void *)(uintptr_t)vaddr, 432 ph->p_memsz)); 433 break; 434 435 #ifdef GNU_RELRO 436 case PT_GNU_RELRO: 437 obj->relro_page = obj->relocbase 438 + round_down(ph->p_vaddr); 439 obj->relro_size = round_up(ph->p_memsz); 440 dbg(("headers: %s %p phsize %" PRImemsz, 441 "PT_GNU_RELRO", (void *)(uintptr_t)vaddr, 442 ph->p_memsz)); 443 break; 444 #endif 445 446 #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) 447 case PT_TLS: 448 obj->tlsindex = 1; 449 obj->tlssize = ph->p_memsz; 450 obj->tlsalign = ph->p_align; 451 obj->tlsinitsize = ph->p_filesz; 452 obj->tlsinit = (void *)(uintptr_t)ph->p_vaddr; 453 dbg(("headers: %s %p phsize %" PRImemsz, 454 "PT_TLS", (void *)(uintptr_t)vaddr, 455 ph->p_memsz)); 456 break; 457 #endif 458 #ifdef __ARM_EABI__ 459 case PT_ARM_EXIDX: 460 obj->exidx_start = (void *)(uintptr_t)vaddr; 461 obj->exidx_sz = ph->p_memsz; 462 dbg(("headers: %s %p phsize %" PRImemsz, 463 "PT_ARM_EXIDX", (void *)(uintptr_t)vaddr, 464 ph->p_memsz)); 465 break; 466 #endif 467 } 468 } 469 assert(nsegs == 2); 470 471 obj->entry = entry; 472 return obj; 473 } 474