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