1 /* $OpenBSD: loader.c,v 1.147 2014/02/16 01:16:38 martynas 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 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 */ 28 29 #define _DYN_LOADER 30 31 #include <sys/types.h> 32 #include <sys/mman.h> 33 #include <sys/exec.h> 34 #include <sys/param.h> 35 #include <sys/sysctl.h> 36 #include <nlist.h> 37 #include <string.h> 38 #include <link.h> 39 #include <dlfcn.h> 40 41 #include "syscall.h" 42 #include "archdep.h" 43 #include "path.h" 44 #include "resolve.h" 45 #include "sod.h" 46 #include "stdlib.h" 47 #include "dl_prebind.h" 48 49 /* 50 * Local decls. 51 */ 52 unsigned long _dl_boot(const char **, char **, const long, long *); 53 void _dl_debug_state(void); 54 void _dl_setup_env(char **); 55 void _dl_dtors(void); 56 void _dl_fixup_user_env(void); 57 void _dl_call_init_recurse(elf_object_t *object, int initfirst); 58 59 const char *_dl_progname; 60 int _dl_pagesz; 61 62 char **_dl_libpath; 63 64 char *_dl_preload; 65 char *_dl_bindnow; 66 char *_dl_traceld; 67 char *_dl_debug; 68 char *_dl_showmap; 69 char *_dl_noprebind; 70 char *_dl_prebind_validate; 71 char *_dl_tracefmt1, *_dl_tracefmt2, *_dl_traceprog; 72 73 int _dl_trust; 74 75 struct r_debug *_dl_debug_map; 76 77 void _dl_dopreload(char *paths); 78 79 /* 80 * Run dtors for all objects that are eligible. 81 */ 82 83 void 84 _dl_run_all_dtors(void) 85 { 86 elf_object_t *node; 87 struct dep_node *dnode; 88 int fini_complete; 89 int skip_initfirst; 90 int initfirst_skipped; 91 92 fini_complete = 0; 93 skip_initfirst = 1; 94 initfirst_skipped = 0; 95 96 while (fini_complete == 0) { 97 fini_complete = 1; 98 for (node = _dl_objects->next; 99 node != NULL; 100 node = node->next) { 101 if ((node->dyn.fini) && 102 (OBJECT_REF_CNT(node) == 0) && 103 (node->status & STAT_INIT_DONE) && 104 ((node->status & STAT_FINI_DONE) == 0)) { 105 if (skip_initfirst && 106 (node->obj_flags & DF_1_INITFIRST)) 107 initfirst_skipped = 1; 108 else 109 node->status |= STAT_FINI_READY; 110 } 111 } 112 for (node = _dl_objects->next; 113 node != NULL; 114 node = node->next ) { 115 if ((node->dyn.fini) && 116 (OBJECT_REF_CNT(node) == 0) && 117 (node->status & STAT_INIT_DONE) && 118 ((node->status & STAT_FINI_DONE) == 0) && 119 (!skip_initfirst || 120 (node->obj_flags & DF_1_INITFIRST) == 0)) 121 TAILQ_FOREACH(dnode, &node->child_list, 122 next_sib) 123 dnode->data->status &= ~STAT_FINI_READY; 124 } 125 126 127 for (node = _dl_objects->next; 128 node != NULL; 129 node = node->next ) { 130 if (node->status & STAT_FINI_READY) { 131 DL_DEB(("doing dtors obj %p @%p: [%s]\n", 132 node, node->dyn.fini, 133 node->load_name)); 134 135 fini_complete = 0; 136 node->status |= STAT_FINI_DONE; 137 node->status &= ~STAT_FINI_READY; 138 (*node->dyn.fini)(); 139 } 140 } 141 142 if (fini_complete && initfirst_skipped) 143 fini_complete = initfirst_skipped = skip_initfirst = 0; 144 } 145 } 146 147 /* 148 * Routine to walk through all of the objects except the first 149 * (main executable). 150 * 151 * Big question, should dlopen()ed objects be unloaded before or after 152 * the destructor for the main application runs? 153 */ 154 void 155 _dl_dtors(void) 156 { 157 _dl_thread_kern_stop(); 158 159 /* ORDER? */ 160 _dl_unload_dlopen(); 161 162 DL_DEB(("doing dtors\n")); 163 164 /* main program runs its dtors itself 165 * but we want to run dtors on all it's children); 166 */ 167 _dl_objects->status |= STAT_FINI_DONE; 168 169 _dl_objects->opencount--; 170 _dl_notify_unload_shlib(_dl_objects); 171 172 _dl_run_all_dtors(); 173 } 174 175 void 176 _dl_dopreload(char *paths) 177 { 178 char *cp, *dp; 179 elf_object_t *shlib; 180 181 dp = paths = _dl_strdup(paths); 182 if (dp == NULL) { 183 _dl_printf("preload: out of memory"); 184 _dl_exit(1); 185 } 186 187 while ((cp = _dl_strsep(&dp, ":")) != NULL) { 188 shlib = _dl_load_shlib(cp, _dl_objects, OBJTYPE_LIB, 189 _dl_objects->obj_flags); 190 if (shlib == NULL) { 191 _dl_printf("%s: can't preload library '%s'\n", 192 _dl_progname, cp); 193 _dl_exit(4); 194 } 195 _dl_add_object(shlib); 196 _dl_link_child(shlib, _dl_objects); 197 } 198 _dl_free(paths); 199 return; 200 } 201 202 /* 203 * grab interesting environment variables, zap bad env vars if 204 * issetugid 205 */ 206 char **_dl_so_envp; 207 void 208 _dl_setup_env(char **envp) 209 { 210 /* 211 * Get paths to various things we are going to use. 212 */ 213 _dl_debug = _dl_getenv("LD_DEBUG", envp); 214 _dl_libpath = _dl_split_path(_dl_getenv("LD_LIBRARY_PATH", envp)); 215 _dl_preload = _dl_getenv("LD_PRELOAD", envp); 216 _dl_bindnow = _dl_getenv("LD_BIND_NOW", envp); 217 _dl_traceld = _dl_getenv("LD_TRACE_LOADED_OBJECTS", envp); 218 _dl_tracefmt1 = _dl_getenv("LD_TRACE_LOADED_OBJECTS_FMT1", envp); 219 _dl_tracefmt2 = _dl_getenv("LD_TRACE_LOADED_OBJECTS_FMT2", envp); 220 _dl_traceprog = _dl_getenv("LD_TRACE_LOADED_OBJECTS_PROGNAME", envp); 221 _dl_noprebind = _dl_getenv("LD_NOPREBIND", envp); 222 _dl_prebind_validate = _dl_getenv("LD_PREBINDVALIDATE", envp); 223 224 /* 225 * Don't allow someone to change the search paths if he runs 226 * a suid program without credentials high enough. 227 */ 228 _dl_trust = !_dl_issetugid(); 229 if (!_dl_trust) { /* Zap paths if s[ug]id... */ 230 if (_dl_libpath) { 231 _dl_free_path(_dl_libpath); 232 _dl_libpath = NULL; 233 _dl_unsetenv("LD_LIBRARY_PATH", envp); 234 } 235 if (_dl_preload) { 236 _dl_preload = NULL; 237 _dl_unsetenv("LD_PRELOAD", envp); 238 } 239 if (_dl_bindnow) { 240 _dl_bindnow = NULL; 241 _dl_unsetenv("LD_BIND_NOW", envp); 242 } 243 if (_dl_debug) { 244 _dl_debug = NULL; 245 _dl_unsetenv("LD_DEBUG", envp); 246 } 247 } 248 _dl_so_envp = envp; 249 250 _dl_trace_setup(envp); 251 } 252 253 int 254 _dl_load_dep_libs(elf_object_t *object, int flags, int booting) 255 { 256 elf_object_t *dynobj; 257 Elf_Dyn *dynp; 258 unsigned int loop; 259 int libcount; 260 int depflags; 261 262 dynobj = object; 263 while (dynobj) { 264 DL_DEB(("examining: '%s'\n", dynobj->load_name)); 265 libcount = 0; 266 267 /* propagate DF_1_NOW to deplibs (can be set by dynamic tags) */ 268 depflags = flags | (dynobj->obj_flags & DF_1_NOW); 269 270 for (dynp = dynobj->load_dyn; dynp->d_tag; dynp++) { 271 if (dynp->d_tag == DT_NEEDED) { 272 libcount++; 273 } 274 } 275 276 if ( libcount != 0) { 277 struct listent { 278 Elf_Dyn *dynp; 279 elf_object_t *depobj; 280 } *liblist; 281 int *randomlist; 282 283 liblist = _dl_malloc(libcount * sizeof(struct listent)); 284 randomlist = _dl_malloc(libcount * sizeof(int)); 285 286 if (liblist == NULL) 287 _dl_exit(5); 288 289 for (dynp = dynobj->load_dyn, loop = 0; dynp->d_tag; 290 dynp++) 291 if (dynp->d_tag == DT_NEEDED) 292 liblist[loop++].dynp = dynp; 293 294 /* Randomize these */ 295 for (loop = 0; loop < libcount; loop++) 296 randomlist[loop] = loop; 297 298 for (loop = 1; loop < libcount; loop++) { 299 unsigned int rnd; 300 int cur; 301 rnd = _dl_random(); 302 rnd = rnd % (loop+1); 303 cur = randomlist[rnd]; 304 randomlist[rnd] = randomlist[loop]; 305 randomlist[loop] = cur; 306 } 307 308 for (loop = 0; loop < libcount; loop++) { 309 elf_object_t *depobj; 310 const char *libname; 311 libname = dynobj->dyn.strtab; 312 libname += 313 liblist[randomlist[loop]].dynp->d_un.d_val; 314 DL_DEB(("loading: %s required by %s\n", libname, 315 dynobj->load_name)); 316 depobj = _dl_load_shlib(libname, dynobj, 317 OBJTYPE_LIB, depflags); 318 if (depobj == 0) { 319 if (booting) { 320 _dl_printf( 321 "%s: can't load library '%s'\n", 322 _dl_progname, libname); 323 _dl_exit(4); 324 } else { 325 DL_DEB(("dlopen: failed to open %s\n", 326 libname)); 327 _dl_free(liblist); 328 return (1); 329 } 330 } 331 liblist[randomlist[loop]].depobj = depobj; 332 } 333 334 for (loop = 0; loop < libcount; loop++) { 335 _dl_add_object(liblist[loop].depobj); 336 _dl_link_child(liblist[loop].depobj, dynobj); 337 } 338 _dl_free(liblist); 339 } 340 dynobj = dynobj->next; 341 } 342 343 /* add first object manually */ 344 _dl_link_grpsym(object, 1); 345 _dl_cache_grpsym_list_setup(object); 346 347 return(0); 348 } 349 350 351 #define PFLAGS(X) ((((X) & PF_R) ? PROT_READ : 0) | \ 352 (((X) & PF_W) ? PROT_WRITE : 0) | \ 353 (((X) & PF_X) ? PROT_EXEC : 0)) 354 355 /* 356 * This is the dynamic loader entrypoint. When entering here, depending 357 * on architecture type, the stack and registers are set up according 358 * to the architectures ABI specification. The first thing required 359 * to do is to dig out all information we need to accomplish our task. 360 */ 361 unsigned long 362 _dl_boot(const char **argv, char **envp, const long dyn_loff, long *dl_data) 363 { 364 struct elf_object *exe_obj; /* Pointer to executable object */ 365 struct elf_object *dyn_obj; /* Pointer to executable object */ 366 struct r_debug **map_link; /* Where to put pointer for gdb */ 367 struct r_debug *debug_map; 368 struct load_list *next_load, *load_list = NULL; 369 Elf_Dyn *dynp; 370 Elf_Phdr *phdp; 371 Elf_Ehdr *ehdr; 372 char *us = NULL; 373 unsigned int loop; 374 int failed; 375 struct dep_node *n; 376 Elf_Addr minva, maxva, exe_loff; 377 int align; 378 379 _dl_setup_env(envp); 380 381 _dl_progname = argv[0]; 382 if (dl_data[AUX_pagesz] != 0) 383 _dl_pagesz = dl_data[AUX_pagesz]; 384 else 385 _dl_pagesz = 4096; 386 387 align = _dl_pagesz - 1; 388 389 #define ROUND_PG(x) (((x) + align) & ~(align)) 390 #define TRUNC_PG(x) ((x) & ~(align)) 391 392 /* 393 * now that GOT and PLT have been relocated, and we know 394 * page size, protect them from modification 395 */ 396 #ifndef RTLD_NO_WXORX 397 { 398 extern char *__got_start; 399 extern char *__got_end; 400 #ifdef RTLD_PROTECT_PLT 401 extern char *__plt_start; 402 extern char *__plt_end; 403 #endif 404 405 _dl_mprotect((void *)ELF_TRUNC((long)&__got_start, _dl_pagesz), 406 ELF_ROUND((long)&__got_end,_dl_pagesz) - 407 ELF_TRUNC((long)&__got_start, _dl_pagesz), 408 GOT_PERMS); 409 410 #ifdef RTLD_PROTECT_PLT 411 /* only for DATA_PLT or BSS_PLT */ 412 _dl_mprotect((void *)ELF_TRUNC((long)&__plt_start, _dl_pagesz), 413 ELF_ROUND((long)&__plt_end,_dl_pagesz) - 414 ELF_TRUNC((long)&__plt_start, _dl_pagesz), 415 PROT_READ|PROT_EXEC); 416 #endif 417 } 418 #endif 419 420 DL_DEB(("rtld loading: '%s'\n", _dl_progname)); 421 422 /* init this in runtime, not statically */ 423 TAILQ_INIT(&_dlopened_child_list); 424 425 exe_obj = NULL; 426 _dl_loading_object = NULL; 427 428 minva = ELFDEFNNAME(NO_ADDR); 429 maxva = exe_loff = 0; 430 431 /* 432 * Examine the user application and set up object information. 433 */ 434 phdp = (Elf_Phdr *)dl_data[AUX_phdr]; 435 for (loop = 0; loop < dl_data[AUX_phnum]; loop++) { 436 switch (phdp->p_type) { 437 case PT_PHDR: 438 exe_loff = (Elf_Addr)dl_data[AUX_phdr] - phdp->p_vaddr; 439 us += exe_loff; 440 DL_DEB(("exe load offset: 0x%lx\n", exe_loff)); 441 break; 442 case PT_DYNAMIC: 443 minva = TRUNC_PG(minva); 444 maxva = ROUND_PG(maxva); 445 exe_obj = _dl_finalize_object(argv[0] ? argv[0] : "", 446 (Elf_Dyn *)(phdp->p_vaddr + exe_loff), 447 (Elf_Phdr *)dl_data[AUX_phdr], 448 dl_data[AUX_phnum], OBJTYPE_EXE, minva + exe_loff, 449 exe_loff); 450 _dl_add_object(exe_obj); 451 break; 452 case PT_INTERP: 453 us += phdp->p_vaddr; 454 break; 455 case PT_LOAD: 456 if (phdp->p_vaddr < minva) 457 minva = phdp->p_vaddr; 458 if (phdp->p_vaddr > maxva) 459 maxva = phdp->p_vaddr + phdp->p_memsz; 460 461 next_load = _dl_malloc(sizeof(struct load_list)); 462 next_load->next = load_list; 463 load_list = next_load; 464 next_load->start = (char *)TRUNC_PG(phdp->p_vaddr) + exe_loff; 465 next_load->size = (phdp->p_vaddr & align) + phdp->p_filesz; 466 next_load->prot = PFLAGS(phdp->p_flags); 467 468 if (phdp->p_flags & 0x08000000) { 469 // dump_prelink(phdp->p_vaddr + exe_loff, phdp->p_memsz); 470 prebind_load_exe(phdp, exe_obj); 471 } 472 break; 473 case PT_TLS: 474 _dl_printf("%s: unsupported TLS program header\n", 475 _dl_progname); 476 _dl_exit(1); 477 break; 478 } 479 phdp++; 480 } 481 exe_obj->load_list = load_list; 482 exe_obj->obj_flags |= DF_1_GLOBAL; 483 exe_obj->load_size = maxva - minva; 484 _dl_set_sod(exe_obj->load_name, &exe_obj->sod); 485 486 n = _dl_malloc(sizeof *n); 487 if (n == NULL) 488 _dl_exit(5); 489 n->data = exe_obj; 490 TAILQ_INSERT_TAIL(&_dlopened_child_list, n, next_sib); 491 exe_obj->opencount++; 492 493 if (_dl_preload != NULL) 494 _dl_dopreload(_dl_preload); 495 496 _dl_load_dep_libs(exe_obj, exe_obj->obj_flags, 1); 497 498 /* 499 * Now add the dynamic loader itself last in the object list 500 * so we can use the _dl_ code when serving dl.... calls. 501 * Intentionally left off the exe child_list. 502 */ 503 dynp = (Elf_Dyn *)((void *)_DYNAMIC); 504 ehdr = (Elf_Ehdr *)dl_data[AUX_base]; 505 dyn_obj = _dl_finalize_object(us, dynp, 506 (Elf_Phdr *)((char *)dl_data[AUX_base] + ehdr->e_phoff), 507 ehdr->e_phnum, OBJTYPE_LDR, dl_data[AUX_base], dyn_loff); 508 _dl_add_object(dyn_obj); 509 510 dyn_obj->refcount++; 511 _dl_link_grpsym(dyn_obj, 1); 512 513 dyn_obj->status |= STAT_RELOC_DONE; 514 _dl_set_sod(dyn_obj->load_name, &dyn_obj->sod); 515 516 /* 517 * Everything should be in place now for doing the relocation 518 * and binding. Call _dl_rtld to do the job. Fingers crossed. 519 */ 520 521 _dl_prebind_pre_resolve(); 522 failed = 0; 523 if (_dl_traceld == NULL) 524 failed = _dl_rtld(_dl_objects); 525 526 _dl_prebind_post_resolve(); 527 528 if (_dl_debug || _dl_traceld) 529 _dl_show_objects(); 530 531 DL_DEB(("dynamic loading done, %s.\n", 532 (failed == 0) ? "success":"failed")); 533 534 if (failed != 0) 535 _dl_exit(1); 536 537 if (_dl_traceld) 538 _dl_exit(0); 539 540 _dl_loading_object = NULL; 541 542 _dl_fixup_user_env(); 543 544 /* 545 * Finally make something to help gdb when poking around in the code. 546 */ 547 map_link = NULL; 548 #ifdef __mips__ 549 map_link = (struct r_debug **)(exe_obj->Dyn.info[DT_MIPS_RLD_MAP - 550 DT_LOPROC + DT_NUM]); 551 #endif 552 if (map_link == NULL) { 553 for (dynp = exe_obj->load_dyn; dynp->d_tag; dynp++) { 554 if (dynp->d_tag == DT_DEBUG) { 555 map_link = (struct r_debug **)&dynp->d_un.d_ptr; 556 break; 557 } 558 } 559 if (dynp->d_tag != DT_DEBUG) 560 DL_DEB(("failed to mark DTDEBUG\n")); 561 } 562 if (map_link) { 563 debug_map = (struct r_debug *)_dl_malloc(sizeof(*debug_map)); 564 debug_map->r_version = 1; 565 debug_map->r_map = (struct link_map *)_dl_objects; 566 debug_map->r_brk = (Elf_Addr)_dl_debug_state; 567 debug_map->r_state = RT_CONSISTENT; 568 debug_map->r_ldbase = dyn_loff; 569 _dl_debug_map = debug_map; 570 #ifdef __mips__ 571 if (dynp->d_tag == DT_DEBUG) 572 _dl_mprotect(map_link, sizeof(*map_link), 573 PROT_READ|PROT_WRITE|PROT_EXEC); 574 #endif 575 *map_link = _dl_debug_map; 576 #ifdef __mips__ 577 if (dynp->d_tag == DT_DEBUG) 578 _dl_mprotect(map_link, sizeof(*map_link), 579 PROT_READ|PROT_EXEC); 580 #endif 581 } 582 583 _dl_debug_state(); 584 585 /* 586 * The first object is the executable itself, 587 * it is responsible for running it's own ctors/dtors 588 * thus do NOT run the ctors for the executable, all of 589 * the shared libraries which follow. 590 * Do not run init code if run from ldd. 591 */ 592 if (_dl_objects->next != NULL) { 593 _dl_objects->status |= STAT_INIT_DONE; 594 _dl_call_init(_dl_objects); 595 } 596 597 DL_DEB(("entry point: 0x%lx\n", dl_data[AUX_entry])); 598 599 /* 600 * Return the entry point. 601 */ 602 return(dl_data[AUX_entry]); 603 } 604 605 #define DL_SM_SYMBUF_CNT 512 606 sym_cache _dl_sm_symcache_buffer[DL_SM_SYMBUF_CNT]; 607 608 int 609 _dl_rtld(elf_object_t *object) 610 { 611 size_t sz; 612 int fails = 0; 613 614 if (object->next) 615 fails += _dl_rtld(object->next); 616 617 if (object->status & STAT_RELOC_DONE) 618 return 0; 619 620 sz = 0; 621 if (object->nchains < DL_SM_SYMBUF_CNT) { 622 _dl_symcache = _dl_sm_symcache_buffer; 623 // DL_DEB(("using static buffer for %d entries\n", 624 // object->nchains)); 625 _dl_memset(_dl_symcache, 0, 626 sizeof (sym_cache) * object->nchains); 627 } else { 628 sz = ELF_ROUND(sizeof (sym_cache) * object->nchains, 629 _dl_pagesz); 630 // DL_DEB(("allocating symcache sz %x with mmap\n", sz)); 631 632 _dl_symcache = (void *)_dl_mmap(0, sz, PROT_READ|PROT_WRITE, 633 MAP_PRIVATE|MAP_ANON, -1, 0); 634 if (_dl_mmap_error(_dl_symcache)) { 635 sz = 0; 636 _dl_symcache = NULL; 637 } 638 } 639 prebind_symcache(object, SYM_NOTPLT); 640 641 /* 642 * Do relocation information first, then GOT. 643 */ 644 fails =_dl_md_reloc(object, DT_REL, DT_RELSZ); 645 fails += _dl_md_reloc(object, DT_RELA, DT_RELASZ); 646 prebind_symcache(object, SYM_PLT); 647 fails += _dl_md_reloc_got(object, !(_dl_bindnow || 648 object->obj_flags & DF_1_NOW)); 649 650 if (_dl_symcache != NULL) { 651 if (sz != 0) 652 _dl_munmap( _dl_symcache, sz); 653 _dl_symcache = NULL; 654 } 655 if (fails == 0) 656 object->status |= STAT_RELOC_DONE; 657 658 return (fails); 659 } 660 661 void 662 _dl_call_init(elf_object_t *object) 663 { 664 _dl_call_init_recurse(object, 1); 665 _dl_call_init_recurse(object, 0); 666 } 667 668 void 669 _dl_call_init_recurse(elf_object_t *object, int initfirst) 670 { 671 struct dep_node *n; 672 673 object->status |= STAT_VISITED; 674 675 TAILQ_FOREACH(n, &object->child_list, next_sib) { 676 if (n->data->status & STAT_VISITED) 677 continue; 678 _dl_call_init_recurse(n->data, initfirst); 679 } 680 681 object->status &= ~STAT_VISITED; 682 683 if (object->status & STAT_INIT_DONE) 684 return; 685 686 if (initfirst && (object->obj_flags & DF_1_INITFIRST) == 0) 687 return; 688 689 if (object->dyn.init) { 690 DL_DEB(("doing ctors obj %p @%p: [%s]\n", 691 object, object->dyn.init, object->load_name)); 692 (*object->dyn.init)(); 693 } 694 695 object->status |= STAT_INIT_DONE; 696 } 697 698 char * 699 _dl_getenv(const char *var, char **env) 700 { 701 const char *ep; 702 703 while ((ep = *env++)) { 704 const char *vp = var; 705 706 while (*vp && *vp == *ep) { 707 vp++; 708 ep++; 709 } 710 if (*vp == '\0' && *ep++ == '=') 711 return((char *)ep); 712 } 713 return(NULL); 714 } 715 716 void 717 _dl_unsetenv(const char *var, char **env) 718 { 719 char *ep; 720 721 while ((ep = *env)) { 722 const char *vp = var; 723 724 while (*vp && *vp == *ep) { 725 vp++; 726 ep++; 727 } 728 if (*vp == '\0' && *ep++ == '=') { 729 char **P; 730 731 for (P = env;; ++P) 732 if (!(*P = *(P + 1))) 733 break; 734 } else 735 env++; 736 } 737 } 738 739 /* 740 * _dl_fixup_user_env() 741 * 742 * Set the user environment so that programs can use the environment 743 * while running constructors. Specifically, MALLOC_OPTIONS= for malloc() 744 */ 745 void 746 _dl_fixup_user_env(void) 747 { 748 const Elf_Sym *sym; 749 Elf_Addr ooff; 750 struct elf_object dummy_obj; 751 752 dummy_obj.dyn.symbolic = 0; 753 dummy_obj.load_name = "ld.so"; 754 755 sym = NULL; 756 ooff = _dl_find_symbol("environ", &sym, 757 SYM_SEARCH_ALL|SYM_NOWARNNOTFOUND|SYM_PLT, NULL, &dummy_obj, NULL); 758 if (sym != NULL) 759 *((char ***)(sym->st_value + ooff)) = _dl_so_envp; 760 } 761