xref: /openbsd/libexec/ld.so/loader.c (revision 91f110e0)
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