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