1 /* $OpenBSD: loader.c,v 1.17 2001/06/13 08:40:39 art Exp $ */ 2 3 /* 4 * Copyright (c) 1998 Per Fogelstrom, Opsycon AB 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed under OpenBSD by 17 * Per Fogelstrom, Opsycon AB, Sweden. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 22 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 */ 34 35 #define _DYN_LOADER 36 37 #include <sys/types.h> 38 #include <sys/mman.h> 39 #include <sys/exec.h> 40 #include <nlist.h> 41 #include <link.h> 42 43 #include "syscall.h" 44 #include "archdep.h" 45 #include "resolve.h" 46 47 /* 48 * Local decls. 49 */ 50 static char *_dl_getenv(const char *var, const char **env); 51 52 /* 53 * Static vars usable after bootsrapping. 54 */ 55 static void *_dl_malloc_base; 56 static void *_dl_malloc_pool = 0; 57 static long *_dl_malloc_free = 0; 58 59 const char *_dl_progname; 60 int _dl_pagesz; 61 int _dl_trusted; 62 63 char *_dl_libpath; 64 char *_dl_preload; 65 char *_dl_bindnow; 66 char *_dl_traceld; 67 char *_dl_debug; 68 char *_dl_showmap; 69 70 struct r_debug *_dl_debug_map; 71 void _dl_unmaphints(); 72 73 void 74 _dl_debug_state(void) 75 { 76 /* Debugger stub */ 77 } 78 79 /* 80 * Routine to walk thru all of the objects except the first (main executable). 81 */ 82 83 void 84 _dl_run_dtors(elf_object_t *object) 85 { 86 DL_DEB(("doing dtors: [%s]\n", object->load_name)); 87 if (object->dyn.fini) { 88 (*object->dyn.fini)(); 89 } 90 if (object->next) { 91 _dl_run_dtors(object->next); 92 } 93 } 94 95 void 96 _dl_dtors(void) 97 { 98 DL_DEB(("doing dtors\n")); 99 if (_dl_objects->next) { 100 _dl_run_dtors(_dl_objects->next); 101 } 102 } 103 104 /* 105 * This is the dynamic loader entrypoint. When entering here, depending 106 * on architecture type, the stack and registers are set up according 107 * to the architectures ABI specification. The first thing required 108 * to do is to dig out all information we need to accomplish out task. 109 */ 110 unsigned long 111 _dl_boot(const char **argv, const char **envp, const long loff, 112 Elf_Dyn *dynp, long *dl_data) 113 { 114 int n; 115 int brk_addr; 116 Elf_Phdr *phdp; 117 char *us = ""; 118 elf_object_t *dynobj; 119 struct elf_object *exe_obj; /* Pointer to executable object */ 120 struct elf_object *dyn_obj; /* Pointer to executable object */ 121 struct r_debug * debug_map; 122 #ifdef __mips__ 123 struct r_debug **map_link; /* Where to put pointer for gdb */ 124 #endif /* __mips__ */ 125 126 /* 127 * Get paths to various things we are going to use. 128 */ 129 130 _dl_libpath = _dl_getenv("LD_LIBRARY_PATH", envp); 131 _dl_preload = _dl_getenv("LD_PRELOAD", envp); 132 _dl_bindnow = _dl_getenv("LD_BIND_NOW", envp); 133 _dl_traceld = _dl_getenv("LD_TRACE_LOADED_OBJECTS", envp); 134 _dl_debug = _dl_getenv("LD_DEBUG", envp); 135 136 _dl_progname = argv[0]; 137 if (dl_data[AUX_pagesz] != 0) { 138 _dl_pagesz = dl_data[AUX_pagesz]; 139 } else { 140 _dl_pagesz = 4096; 141 } 142 DL_DEB(("rtld loading: '%s'\n", _dl_progname)); 143 144 /* 145 * Don't allow someone to change the search paths if he runs 146 * a suid program without credentials high enough. 147 */ 148 if ((_dl_trusted = !_dl_suid_ok())) { /* Zap paths if s[ug]id... */ 149 if (_dl_preload) { 150 *_dl_preload = '\0'; 151 } 152 if (_dl_libpath) { 153 *_dl_libpath = '\0'; 154 } 155 } 156 157 /* 158 * Examine the user application and set up object information. 159 */ 160 phdp = (Elf_Phdr *)dl_data[AUX_phdr]; 161 for (n = 0; n < dl_data[AUX_phnum]; n++) { 162 if (phdp->p_type == PT_LOAD) { /*XXX*/ 163 if (phdp->p_vaddr + phdp->p_memsz > brk_addr) /*XXX*/ 164 brk_addr = phdp->p_vaddr + phdp->p_memsz; 165 } /*XXX*/ 166 if (phdp->p_type == PT_DYNAMIC) { 167 exe_obj = _dl_add_object("", (Elf_Dyn *)phdp->p_vaddr, 168 dl_data, OBJTYPE_EXE, 0, 0); 169 } 170 if (phdp->p_type == PT_INTERP) { 171 us = (char *)_dl_malloc(_dl_strlen((char *)phdp->p_vaddr) + 1); 172 _dl_strcpy(us, (char *)phdp->p_vaddr); 173 } 174 phdp++; 175 } 176 177 /* 178 * Now, pick up and 'load' all libraries requierd. Start 179 * With the first on the list and then do whatever gets 180 * added along the tour. 181 */ 182 183 dynobj = _dl_objects; 184 while (dynobj) { 185 DL_DEB(("examining: '%s'\n", dynobj->load_name)); 186 for (dynp = dynobj->load_dyn; dynp->d_tag; dynp++) { 187 const char *libname; 188 189 if (dynp->d_tag != DT_NEEDED) 190 continue; 191 libname = dynobj->dyn.strtab; 192 libname += dynp->d_un.d_val; 193 DL_DEB(("needs: '%s'\n", libname)); 194 if (_dl_load_shlib(libname, dynobj, OBJTYPE_LIB) == 0) { 195 _dl_printf("%s: can't load library '%s'\n", 196 _dl_progname, libname); 197 _dl_exit(4); 198 } 199 } 200 dynobj = dynobj->next; 201 } 202 203 /* 204 * Now add the dynamic loader itself last in the object list 205 * so we can use the _dl_ code when serving dl.... calls. 206 */ 207 208 dynp = (Elf_Dyn *)((void *)_DYNAMIC); 209 dyn_obj = _dl_add_object(us, dynp, 0, OBJTYPE_LDR, dl_data[AUX_base], loff); 210 dyn_obj->status |= STAT_RELOC_DONE; 211 212 /* 213 * Everything should be in place now for doing the relocation 214 * and binding. Call _dl_rtld to do the job. Fingers crossed. 215 */ 216 217 _dl_rtld(_dl_objects); 218 219 /* 220 * The first object is the executable itself, 221 * it is responsible for running it's own ctors/dtors 222 * thus do NOT run the ctors for the executable, all of 223 * the shared libraries which follow. 224 */ 225 if (_dl_objects->next) { 226 _dl_call_init(_dl_objects->next); 227 } 228 229 /* 230 * Schedule a routine to be run at shutdown, by using atexit. 231 * cannot call atexit directly from ld.so? 232 */ 233 { 234 const Elf_Sym *sym; 235 Elf_Addr ooff; 236 237 ooff = _dl_find_symbol("atexit", _dl_objects, &sym, 0, 0); 238 if (sym == NULL) { 239 _dl_printf("cannot find atexit, destructors will not be run!\n"); 240 } else { 241 (*(void (*)(Elf_Addr))(sym->st_value + ooff))((Elf_Addr)_dl_dtors); 242 } 243 } 244 245 246 /* 247 * Finally make something to help gdb when poking around in the code. 248 */ 249 #if defined(__powerpc__) || defined(__alpha__) 250 debug_map = (struct r_debug *)_dl_malloc(sizeof(*debug_map)); 251 debug_map->r_version = 1; 252 debug_map->r_map = (struct link_map *)_dl_objects; 253 debug_map->r_brk = (Elf_Addr)_dl_debug_state; 254 debug_map->r_state = RT_CONSISTENT; 255 debug_map->r_ldbase = loff; 256 _dl_debug_map = debug_map; 257 258 /* Picks up the first object, the executable itself */ 259 dynobj = _dl_objects; 260 261 for (dynp = dynobj->load_dyn; dynp->d_tag; dynp++) { 262 if (dynp->d_tag == DT_DEBUG) { 263 dynp->d_un.d_ptr = (Elf_Addr) debug_map; 264 break; 265 } 266 } 267 if (dynp->d_tag != DT_DEBUG) { 268 _dl_printf("failed to mark DTDEBUG\n"); 269 } 270 #endif 271 272 #ifdef __mips__ 273 map_link = (struct r_debug **)(exe_obj->Dyn.info[DT_MIPS_RLD_MAP - DT_LOPROC + DT_NUM]); 274 if (map_link) { 275 debug_map = (struct r_debug *)_dl_malloc(sizeof(*debug_map)); 276 debug_map->r_version = 1; 277 debug_map->r_map = (struct link_map *)_dl_objects; 278 debug_map->r_brk = (Elf_Addr)_dl_debug_state; 279 debug_map->r_state = RT_CONSISTENT; 280 debug_map->r_ldbase = loff; 281 _dl_debug_map = debug_map; 282 *map_link = _dl_debug_map; 283 } 284 #endif 285 286 _dl_debug_state(); 287 288 if (_dl_debug || _dl_traceld) { 289 void _dl_show_objects(); /* remove -Wall warning */ 290 _dl_show_objects(); 291 DL_DEB(("dynamic loading done.\n")); 292 } 293 _dl_unmaphints(); 294 if (_dl_traceld) { 295 _dl_exit(0); 296 } 297 298 /* 299 * Return the entry point. 300 */ 301 return(dl_data[AUX_entry]); 302 } 303 304 305 void 306 _dl_boot_bind(const long sp, const long loff, int argc, const char **argv, 307 const char **envp, Elf_Dyn *dynamicp, long *dl_data) 308 { 309 AuxInfo *auxstack; 310 long *stack; 311 Elf_Dyn *dynp; 312 int n; 313 314 struct elf_object dynld; /* Resolver data for the loader */ 315 316 /* 317 * Scan argument and environment vectors. Find dynamic 318 * data vector put after them. 319 */ 320 #ifdef _mips_ 321 stack = (long *)sp; 322 argc = *stack++; 323 argv = (const char **)stack; 324 envp = &argv[argc + 1]; 325 #endif /* _mips_ */ 326 stack = (long *)envp; 327 while(*stack++ != NULL) {}; 328 329 /* 330 * Dig out auxiliary data set up by exec call. Move all known 331 * tags to an indexed local table for easy access. 332 */ 333 334 auxstack = (AuxInfo *)stack; 335 336 while (auxstack->au_id != AUX_null) { 337 if (auxstack->au_id <= AUX_entry) { 338 dl_data[auxstack->au_id] = auxstack->au_v; 339 } 340 auxstack++; 341 } 342 343 /* 344 * We need to do 'selfreloc' in case the code weren't 345 * loaded at the address it was linked to. 346 * 347 * Scan the DYNAMIC section for the loader. 348 * Cache the data for easier access. 349 */ 350 351 #if defined(__powerpc__) || defined(__alpha__) 352 dynp = dynamicp; 353 #else 354 dynp = (Elf_Dyn *)((long)_DYNAMIC + loff); 355 #endif 356 while (dynp != NULL && dynp->d_tag != DT_NULL) { 357 if (dynp->d_tag < DT_LOPROC) { 358 dynld.Dyn.info[dynp->d_tag] = dynp->d_un.d_val; 359 } else if (dynp->d_tag >= DT_LOPROC && dynp->d_tag < DT_LOPROC + DT_NUM) { 360 dynld.Dyn.info[dynp->d_tag + DT_NUM - DT_LOPROC] = dynp->d_un.d_val; 361 } 362 if (dynp->d_tag == DT_TEXTREL) 363 dynld.dyn.textrel = 1; 364 dynp++; 365 } 366 367 /* 368 * Do the 'bootstrap relocation'. This is really only needed if 369 * the code was loaded at another location than it was linked to. 370 * We don't do undefined symbols resolving (to difficult..) 371 */ 372 373 /* "relocate" dyn.X values if they represent addresses */ 374 { 375 int i, val; 376 /* must be code, not pic data */ 377 int table[20]; 378 i = 0; 379 table[i++] = DT_PLTGOT; 380 table[i++] = DT_HASH; 381 table[i++] = DT_STRTAB; 382 table[i++] = DT_SYMTAB; 383 table[i++] = DT_RELA; 384 table[i++] = DT_INIT; 385 table[i++] = DT_FINI; 386 table[i++] = DT_REL; 387 table[i++] = DT_JMPREL; 388 /* other processors insert their extras here */ 389 table[i++] = DT_NULL; 390 for (i = 0; table[i] != DT_NULL; i++) { 391 val = table[i]; 392 if (val > DT_HIPROC) /* ??? */ 393 continue; 394 if (val > DT_LOPROC) 395 val -= DT_LOPROC + DT_NUM; 396 if (dynld.Dyn.info[val] != 0) 397 dynld.Dyn.info[val] += loff; 398 } 399 400 } 401 402 { 403 int i; 404 u_int32_t rs; 405 Elf_Rel *rp; 406 407 rp = (Elf_Rel *)(dynld.Dyn.info[DT_REL]); 408 rs = dynld.dyn.relsz; 409 410 for (i = 0; i < rs; i += sizeof (Elf_Rel)) { 411 Elf_Addr *ra; 412 const Elf_Sym *sp; 413 414 sp = dynld.dyn.symtab; 415 sp += ELF_R_SYM(rp->r_info); 416 417 if (ELF_R_SYM(rp->r_info) && sp->st_value == 0) { 418 #if 0 419 /* cannot printf in this function */ 420 _dl_wrstderr("Dynamic loader failure: self bootstrapping impossible.\n"); 421 _dl_wrstderr("Undefined symbol: "); 422 _dl_wrstderr((char *)dynld.dyn.strtab 423 + sp->st_name); 424 #endif 425 _dl_exit(5); 426 } 427 428 ra = (Elf_Addr *)(rp->r_offset + loff); 429 /* 430 RELOC_REL(rp, sp, ra, loff); 431 */ 432 rp++; 433 } 434 435 } 436 for (n = 0; n < 2; n++) { 437 int i; 438 unsigned long rs; 439 Elf_RelA *rp; 440 441 switch (n) { 442 case 0: 443 rp = (Elf_RelA *)(dynld.Dyn.info[DT_JMPREL]); 444 rs = dynld.dyn.pltrelsz; 445 break; 446 case 1: 447 rp = (Elf_RelA *)(dynld.Dyn.info[DT_RELA]); 448 rs = dynld.dyn.relasz; 449 break; 450 default: 451 rp = NULL; 452 rs = 0; 453 } 454 for (i = 0; i < rs; i += sizeof (Elf_RelA)) { 455 Elf_Addr *ra; 456 const Elf_Sym *sp; 457 458 sp = dynld.dyn.symtab; 459 sp += ELF_R_SYM(rp->r_info); 460 if (ELF_R_SYM(rp->r_info) && sp->st_value == 0) { 461 #if 0 462 _dl_wrstderr("Dynamic loader failure: self bootstrapping impossible.\n"); 463 _dl_wrstderr("Undefined symbol: "); 464 _dl_wrstderr((char *)dynld.dyn.strtab 465 + sp->st_name); 466 #endif 467 _dl_exit(6); 468 } 469 470 ra = (Elf_Addr *)(rp->r_offset + loff); 471 472 RELOC_RELA(rp, sp, ra, loff); 473 474 rp++; 475 } 476 } 477 /* 478 * we have been fully relocated here, so most things no longer 479 * need the loff adjustment 480 */ 481 return; 482 } 483 484 485 void 486 _dl_rtld(elf_object_t *object) 487 { 488 if (object->next) { 489 _dl_rtld(object->next); 490 } 491 492 /* 493 * Do relocation information first, then GOT. 494 */ 495 _dl_md_reloc(object, DT_REL, DT_RELSZ); 496 _dl_md_reloc(object, DT_RELA, DT_RELASZ); 497 if (_dl_bindnow || object->dyn.bind_now) { /* XXX Perhaps more checking ? */ 498 _dl_md_reloc_got(object, 0); 499 } else { 500 _dl_md_reloc_got(object, 1); 501 } 502 object->status |= STAT_RELOC_DONE; 503 } 504 505 void 506 _dl_call_init(elf_object_t *object) 507 { 508 Elf_Addr ooff; 509 const Elf_Sym *sym; 510 static void (*_dl_atexit)(Elf_Addr) = NULL; 511 512 if (object->next) { 513 _dl_call_init(object->next); 514 } 515 516 if (object->status & STAT_INIT_DONE) { 517 return; 518 } 519 520 #ifndef __mips__ 521 if(object->dyn.init) { 522 (*object->dyn.init)(); 523 } 524 /* 525 * XXX We perform relocation of DTOR/CTOR. This is a ld bug problem 526 * XXX that should be fixed. 527 */ 528 sym = 0; 529 ooff = _dl_find_symbol("__CTOR_LIST__", object, &sym, 1, 1); 530 if (sym) { 531 int i = *(int *)(sym->st_value + ooff); 532 while(i--) { 533 *(int *)(sym->st_value + ooff + 4 + 4 * i) += ooff; 534 } 535 } 536 sym = 0; 537 ooff = _dl_find_symbol("__DTOR_LIST__", object, &sym, 1, 1); 538 if (sym) { 539 int i = *(int *)(sym->st_value + ooff); 540 while(i--) { 541 *(int *)(sym->st_value + ooff + 4 + 4 * i) += ooff; 542 } 543 } 544 545 /* 546 * XXX We should really call any code which resides in the .init segment 547 * XXX but at the moment this functionality is not provided by the toolchain. 548 * XXX Instead we rely on a symbol named '.init' and call it if it exists. 549 */ 550 sym = 0; 551 ooff = _dl_find_symbol(".init", object, &sym, 1, 1); 552 if (sym) { 553 DL_DEB(("calling .init in '%s'\n",object->load_name)); 554 (*(void(*)(void))(sym->st_value + ooff))(); 555 } 556 #if 0 /*XXX*/ 557 if (object->dyn.init) { 558 (*object->dyn.init)(); 559 } 560 #endif 561 #endif /* __mips__ */ 562 object->status |= STAT_INIT_DONE; 563 } 564 565 static char * 566 _dl_getenv(const char *var, const char **env) 567 { 568 const char *ep; 569 570 while ((ep = *env++)) { 571 const char *vp = var; 572 573 while (*vp && *vp == *ep) { 574 vp++; 575 ep++; 576 } 577 if (*vp == '\0' && *ep++ == '=') { 578 return((char *)ep); 579 } 580 } 581 582 return(0); 583 } 584 585 586 /* 587 * The following malloc/free code is a very simplified implementation 588 * of a malloc function. However, we do not need to be very complex here 589 * because we only free memory when 'dlclose()' is called and we can 590 * reuse at least the memory allocated for the object descriptor. We have 591 * one dynamic string allocated, the library name and it is likely that 592 * we can reuse that one to without a lot of complex colapsing code. 593 */ 594 595 void * 596 _dl_malloc(int size) 597 { 598 long *p; 599 long *t, *n; 600 601 size = (size + 8 + DL_MALLOC_ALIGN - 1) & ~(DL_MALLOC_ALIGN - 1); 602 603 if ((t = _dl_malloc_free) != 0) { /* Try free list first */ 604 n = (long *)&_dl_malloc_free; 605 while (t && t[-1] < size) { 606 n = t; 607 t = (long *)*t; 608 } 609 if (t) { 610 *n = *t; 611 _dl_memset(t, 0, t[-1] - 4); 612 return((void *)t); 613 } 614 } 615 if ((_dl_malloc_pool == 0) || 616 (_dl_malloc_pool + size > _dl_malloc_base + 4096)) { 617 _dl_malloc_pool = (void *)_dl_mmap((void *)0, 4096, 618 PROT_READ|PROT_WRITE, 619 MAP_ANON|MAP_PRIVATE, -1, 0); 620 if (_dl_malloc_pool == 0 || _dl_malloc_pool == MAP_FAILED ) { 621 _dl_printf("Dynamic loader failure: malloc.\n"); 622 _dl_exit(7); 623 } 624 _dl_malloc_base = _dl_malloc_pool; 625 } 626 p = _dl_malloc_pool; 627 _dl_malloc_pool += size; 628 _dl_memset(p, 0, size); 629 *p = size; 630 return((void *)(p + 1)); 631 } 632 633 void 634 _dl_free(void *p) 635 { 636 long *t = (long *)p; 637 638 *t = (long)_dl_malloc_free; 639 _dl_malloc_free = p; 640 } 641