xref: /openbsd/libexec/ld.so/loader.c (revision 17df1aa7)
1 /*	$OpenBSD: loader.c,v 1.118 2010/01/02 12:16:35 kettenis 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 "resolve.h"
44 #include "sod.h"
45 #include "stdlib.h"
46 #include "dl_prebind.h"
47 
48 #include "../../lib/csu/common_elf/os-note-elf.h"
49 
50 /*
51  * Local decls.
52  */
53 static char *_dl_getenv(const char *, char **);
54 static void _dl_unsetenv(const char *, char **);
55 unsigned long _dl_boot(const char **, char **, const long, long *);
56 void _dl_debug_state(void);
57 void _dl_setup_env(char **);
58 void _dl_dtors(void);
59 void _dl_boot_bind(const long, long *, Elf_Dyn *);
60 void _dl_fixup_user_env(void);
61 
62 const char *_dl_progname;
63 int  _dl_pagesz;
64 
65 char *_dl_libpath;
66 char *_dl_preload;
67 char *_dl_bindnow;
68 char *_dl_traceld;
69 char *_dl_debug;
70 char *_dl_showmap;
71 char *_dl_norandom;
72 char *_dl_noprebind;
73 char *_dl_prebind_validate;
74 char *_dl_tracefmt1, *_dl_tracefmt2, *_dl_traceprog;
75 
76 struct r_debug *_dl_debug_map;
77 
78 void _dl_dopreload(char *paths);
79 
80 void
81 _dl_debug_state(void)
82 {
83 	/* Debugger stub */
84 }
85 
86 /*
87  * Run dtors for all objects that are eligible.
88  */
89 
90 void
91 _dl_run_all_dtors()
92 {
93 	elf_object_t *node;
94 	int fini_complete;
95 	struct dep_node *dnode;
96 
97 	fini_complete = 0;
98 
99 	while (fini_complete == 0) {
100 		fini_complete = 1;
101 		for (node = _dl_objects->next;
102 		    node != NULL;
103 		    node = node->next) {
104 			if ((node->dyn.fini) &&
105 			    (OBJECT_REF_CNT(node) == 0) &&
106 			    (node->status & STAT_INIT_DONE) &&
107 			    ((node->status & STAT_FINI_DONE) == 0)) {
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 				TAILQ_FOREACH(dnode, &node->child_list,
119 				    next_sib)
120 					dnode->data->status &= ~STAT_FINI_READY;
121 		}
122 
123 
124 		for (node = _dl_objects->next;
125 		    node != NULL;
126 		    node = node->next ) {
127 			if (node->status & STAT_FINI_READY) {
128 				DL_DEB(("doing dtors obj %p @%p: [%s]\n",
129 				    node, node->dyn.fini,
130 				    node->load_name));
131 
132 				fini_complete = 0;
133 				node->status |= STAT_FINI_DONE;
134 				node->status &= ~STAT_FINI_READY;
135 				(*node->dyn.fini)();
136 			}
137 		}
138 	}
139 }
140 
141 /*
142  * Routine to walk through all of the objects except the first
143  * (main executable).
144  *
145  * Big question, should dlopen()ed objects be unloaded before or after
146  * the destructor for the main application runs?
147  */
148 void
149 _dl_dtors(void)
150 {
151 	_dl_thread_kern_stop();
152 
153 	/* ORDER? */
154 	_dl_unload_dlopen();
155 
156 	DL_DEB(("doing dtors\n"));
157 
158 	/* main program runs its dtors itself
159 	 * but we want to run dtors on all it's children);
160 	 */
161 	_dl_objects->status |= STAT_FINI_DONE;
162 
163 	_dl_objects->opencount--;
164 	_dl_notify_unload_shlib(_dl_objects);
165 
166 	_dl_run_all_dtors();
167 }
168 
169 void
170 _dl_dopreload(char *paths)
171 {
172 	char		*cp, *dp;
173 	elf_object_t	*shlib;
174 
175 	dp = paths = _dl_strdup(paths);
176 	if (dp == NULL) {
177 		_dl_printf("preload: out of memory");
178 		_dl_exit(1);
179 	}
180 
181 	while ((cp = _dl_strsep(&dp, ":")) != NULL) {
182 		shlib = _dl_load_shlib(cp, _dl_objects, OBJTYPE_LIB,
183 		_dl_objects->obj_flags);
184 		if (shlib == NULL) {
185 			_dl_printf("%s: can't load library '%s'\n",
186 			    _dl_progname, cp);
187 			_dl_exit(4);
188 		}
189 		_dl_add_object(shlib);
190 		_dl_link_child(shlib, _dl_objects);
191 	}
192 	_dl_free(paths);
193 	return;
194 }
195 
196 /*
197  * grab interesting environment variables, zap bad env vars if
198  * issetugid
199  */
200 char **_dl_so_envp;
201 void
202 _dl_setup_env(char **envp)
203 {
204 	/*
205 	 * Get paths to various things we are going to use.
206 	 */
207 	_dl_libpath = _dl_getenv("LD_LIBRARY_PATH", envp);
208 	_dl_preload = _dl_getenv("LD_PRELOAD", envp);
209 	_dl_bindnow = _dl_getenv("LD_BIND_NOW", envp);
210 	_dl_traceld = _dl_getenv("LD_TRACE_LOADED_OBJECTS", envp);
211 	_dl_tracefmt1 = _dl_getenv("LD_TRACE_LOADED_OBJECTS_FMT1", envp);
212 	_dl_tracefmt2 = _dl_getenv("LD_TRACE_LOADED_OBJECTS_FMT2", envp);
213 	_dl_traceprog = _dl_getenv("LD_TRACE_LOADED_OBJECTS_PROGNAME", envp);
214 	_dl_debug = _dl_getenv("LD_DEBUG", envp);
215 	_dl_norandom = _dl_getenv("LD_NORANDOM", envp);
216 	_dl_noprebind = _dl_getenv("LD_NOPREBIND", envp);
217 	_dl_prebind_validate = _dl_getenv("LD_PREBINDVALIDATE", envp);
218 
219 	/*
220 	 * Don't allow someone to change the search paths if he runs
221 	 * a suid program without credentials high enough.
222 	 */
223 	if (_dl_issetugid()) {	/* Zap paths if s[ug]id... */
224 		if (_dl_libpath) {
225 			_dl_libpath = NULL;
226 			_dl_unsetenv("LD_LIBRARY_PATH", envp);
227 		}
228 		if (_dl_preload) {
229 			_dl_preload = NULL;
230 			_dl_unsetenv("LD_PRELOAD", envp);
231 		}
232 		if (_dl_bindnow) {
233 			_dl_bindnow = NULL;
234 			_dl_unsetenv("LD_BIND_NOW", envp);
235 		}
236 		if (_dl_debug) {
237 			_dl_debug = NULL;
238 			_dl_unsetenv("LD_DEBUG", envp);
239 		}
240 		if (_dl_norandom) {
241 			_dl_norandom = NULL;
242 			_dl_unsetenv("LD_NORANDOM", envp);
243 		}
244 	}
245 	_dl_so_envp = envp;
246 }
247 
248 int
249 _dl_load_dep_libs(elf_object_t *object, int flags, int booting)
250 {
251 	elf_object_t *dynobj;
252 	Elf_Dyn *dynp;
253 	unsigned int loop;
254 	int libcount;
255 	int depflags;
256 
257 	dynobj = object;
258 	while (dynobj) {
259 		DL_DEB(("examining: '%s'\n", dynobj->load_name));
260 		libcount = 0;
261 
262 		/* propagate RTLD_NOW to deplibs (can be set by dynamic tags) */
263 		depflags = flags | (dynobj->obj_flags & RTLD_NOW);
264 
265 		for (dynp = dynobj->load_dyn; dynp->d_tag; dynp++) {
266 			if (dynp->d_tag == DT_NEEDED) {
267 				libcount++;
268 			}
269 		}
270 
271 		if ( libcount != 0) {
272 			struct listent {
273 				Elf_Dyn *dynp;
274 				elf_object_t *depobj;
275 			} *liblist;
276 			int *randomlist;
277 
278 			liblist = _dl_malloc(libcount * sizeof(struct listent));
279 			randomlist =  _dl_malloc(libcount * sizeof(int));
280 
281 			if (liblist == NULL)
282 				_dl_exit(5);
283 
284 			for (dynp = dynobj->load_dyn, loop = 0; dynp->d_tag;
285 			    dynp++)
286 				if (dynp->d_tag == DT_NEEDED)
287 					liblist[loop++].dynp = dynp;
288 
289 			/* Randomize these */
290 			for (loop = 0; loop < libcount; loop++)
291 				randomlist[loop] = loop;
292 
293 			if (!_dl_norandom)
294 				for (loop = 1; loop < libcount; loop++) {
295 					unsigned int rnd;
296 					int cur;
297 					rnd = _dl_random();
298 					rnd = rnd % (loop+1);
299 					cur = randomlist[rnd];
300 					randomlist[rnd] = randomlist[loop];
301 					randomlist[loop] = cur;
302 				}
303 
304 			for (loop = 0; loop < libcount; loop++) {
305 				elf_object_t *depobj;
306 				const char *libname;
307 				libname = dynobj->dyn.strtab;
308 				libname +=
309 				    liblist[randomlist[loop]].dynp->d_un.d_val;
310 				DL_DEB(("loading: %s required by %s\n", libname,
311 				    dynobj->load_name));
312 				depobj = _dl_load_shlib(libname, dynobj,
313 				    OBJTYPE_LIB, depflags);
314 				if (depobj == 0) {
315 					if (booting) {
316 						_dl_printf(
317 						    "%s: can't load library '%s'\n",
318 						    _dl_progname, libname);
319 						_dl_exit(4);
320 					} else  {
321 						DL_DEB(("dlopen: failed to open %s\n",
322 						    libname));
323 						_dl_free(liblist);
324 						return (1);
325 					}
326 				}
327 				liblist[randomlist[loop]].depobj = depobj;
328 			}
329 
330 			for (loop = 0; loop < libcount; loop++) {
331 				_dl_add_object(liblist[loop].depobj);
332 				_dl_link_child(liblist[loop].depobj, dynobj);
333 			}
334 			_dl_free(liblist);
335 		}
336 		dynobj = dynobj->next;
337 	}
338 
339 	/* add first object manually */
340 	_dl_link_grpsym(object);
341 	_dl_cache_grpsym_list(object);
342 
343 	return(0);
344 }
345 
346 
347 #define PFLAGS(X) ((((X) & PF_R) ? PROT_READ : 0) | \
348 		   (((X) & PF_W) ? PROT_WRITE : 0) | \
349 		   (((X) & PF_X) ? PROT_EXEC : 0))
350 
351 /*
352  * This is the dynamic loader entrypoint. When entering here, depending
353  * on architecture type, the stack and registers are set up according
354  * to the architectures ABI specification. The first thing required
355  * to do is to dig out all information we need to accomplish our task.
356  */
357 unsigned long
358 _dl_boot(const char **argv, char **envp, const long dyn_loff, long *dl_data)
359 {
360 	struct elf_object *exe_obj;	/* Pointer to executable object */
361 	struct elf_object *dyn_obj;	/* Pointer to executable object */
362 	struct r_debug **map_link;	/* Where to put pointer for gdb */
363 	struct r_debug *debug_map;
364 	struct load_list *next_load, *load_list = NULL;
365 	Elf_Dyn *dynp;
366 	Elf_Phdr *phdp;
367 	Elf_Ehdr *ehdr;
368 	char *us = NULL;
369 	unsigned int loop;
370 	int failed;
371 	struct dep_node *n;
372 	Elf_Addr minva, maxva, exe_loff;
373 	int align;
374 
375 	_dl_setup_env(envp);
376 
377 	_dl_progname = argv[0];
378 	if (dl_data[AUX_pagesz] != 0)
379 		_dl_pagesz = dl_data[AUX_pagesz];
380 	else
381 		_dl_pagesz = 4096;
382 
383 	align = _dl_pagesz - 1;
384 
385 #define ROUND_PG(x) (((x) + align) & ~(align))
386 #define TRUNC_PG(x) ((x) & ~(align))
387 
388 	/*
389 	 * now that GOT and PLT has been relocated, and we know
390 	 * page size, protect it from modification
391 	 */
392 #ifndef  RTLD_NO_WXORX
393 	{
394 		extern char *__got_start;
395 		extern char *__got_end;
396 #ifdef RTLD_PROTECT_PLT
397 		extern char *__plt_start;
398 		extern char *__plt_end;
399 #endif
400 
401 		_dl_mprotect((void *)ELF_TRUNC((long)&__got_start, _dl_pagesz),
402 		    ELF_ROUND((long)&__got_end,_dl_pagesz) -
403 		    ELF_TRUNC((long)&__got_start, _dl_pagesz),
404 		    GOT_PERMS);
405 
406 #ifdef RTLD_PROTECT_PLT
407 		/* only for DATA_PLT or BSS_PLT */
408 		_dl_mprotect((void *)ELF_TRUNC((long)&__plt_start, _dl_pagesz),
409 		    ELF_ROUND((long)&__plt_end,_dl_pagesz) -
410 		    ELF_TRUNC((long)&__plt_start, _dl_pagesz),
411 		    PROT_READ|PROT_EXEC);
412 #endif
413 	}
414 #endif
415 
416 	DL_DEB(("rtld loading: '%s'\n", _dl_progname));
417 
418 	/* init this in runtime, not statically */
419 	TAILQ_INIT(&_dlopened_child_list);
420 
421 	exe_obj = NULL;
422 	_dl_loading_object = NULL;
423 
424 	minva = ELFDEFNNAME(NO_ADDR);
425 	maxva = exe_loff = 0;
426 
427 	/*
428 	 * Examine the user application and set up object information.
429 	 */
430 	phdp = (Elf_Phdr *)dl_data[AUX_phdr];
431 	for (loop = 0; loop < dl_data[AUX_phnum]; loop++) {
432 		switch (phdp->p_type) {
433 		case PT_PHDR:
434 			exe_loff = (Elf_Addr)dl_data[AUX_phdr] - phdp->p_vaddr;
435 			us += exe_loff;
436 			DL_DEB(("exe load offset:  0x%lx\n", exe_loff));
437 			break;
438 		case PT_DYNAMIC:
439 			minva = TRUNC_PG(minva);
440 			maxva = ROUND_PG(maxva);
441 			exe_obj = _dl_finalize_object(argv[0] ? argv[0] : "",
442 			    (Elf_Dyn *)(phdp->p_vaddr + exe_loff),
443 			    (Elf_Phdr *)dl_data[AUX_phdr],
444 			    dl_data[AUX_phnum], OBJTYPE_EXE, minva + exe_loff,
445 			    exe_loff);
446 			_dl_add_object(exe_obj);
447 			break;
448 		case PT_INTERP:
449 			us += phdp->p_vaddr;
450 			break;
451 		case PT_LOAD:
452 			if (phdp->p_vaddr < minva)
453 				minva = phdp->p_vaddr;
454 			if (phdp->p_vaddr > maxva)
455 				maxva = phdp->p_vaddr + phdp->p_memsz;
456 
457 			next_load = _dl_malloc(sizeof(struct load_list));
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 		}
470 		phdp++;
471 	}
472 	exe_obj->load_list = load_list;
473 	exe_obj->obj_flags |= RTLD_GLOBAL;
474 	exe_obj->load_size = maxva - minva;
475 
476 	n = _dl_malloc(sizeof *n);
477 	if (n == NULL)
478 		_dl_exit(5);
479 	n->data = exe_obj;
480 	TAILQ_INSERT_TAIL(&_dlopened_child_list, n, next_sib);
481 	exe_obj->opencount++;
482 
483 	if (_dl_preload != NULL)
484 		_dl_dopreload(_dl_preload);
485 
486 	_dl_load_dep_libs(exe_obj, exe_obj->obj_flags, 1);
487 
488 	/*
489 	 * Now add the dynamic loader itself last in the object list
490 	 * so we can use the _dl_ code when serving dl.... calls.
491 	 * Intentionally left off the exe child_list.
492 	 */
493 	dynp = (Elf_Dyn *)((void *)_DYNAMIC);
494 	ehdr = (Elf_Ehdr *)dl_data[AUX_base];
495         dyn_obj = _dl_finalize_object(us, dynp,
496 	    (Elf_Phdr *)((char *)dl_data[AUX_base] + ehdr->e_phoff),
497 	    ehdr->e_phnum, OBJTYPE_LDR, dl_data[AUX_base], dyn_loff);
498 	_dl_add_object(dyn_obj);
499 
500 	dyn_obj->refcount++;
501 	_dl_link_grpsym(dyn_obj);
502 
503 	dyn_obj->status |= STAT_RELOC_DONE;
504 
505 	/*
506 	 * Everything should be in place now for doing the relocation
507 	 * and binding. Call _dl_rtld to do the job. Fingers crossed.
508 	 */
509 
510 	_dl_prebind_pre_resolve();
511 	failed = 0;
512 	if (_dl_traceld == NULL)
513 		failed = _dl_rtld(_dl_objects);
514 
515 	_dl_prebind_post_resolve();
516 
517 	if (_dl_debug || _dl_traceld)
518 		_dl_show_objects();
519 
520 	DL_DEB(("dynamic loading done, %s.\n",
521 	    (failed == 0) ? "success":"failed"));
522 
523 	if (failed != 0)
524 		_dl_exit(1);
525 
526 	if (_dl_traceld)
527 		_dl_exit(0);
528 
529 	_dl_loading_object = NULL;
530 
531 	_dl_fixup_user_env();
532 
533 	/*
534 	 * Finally make something to help gdb when poking around in the code.
535 	 */
536 #ifdef __mips__
537 	map_link = (struct r_debug **)(exe_obj->Dyn.info[DT_MIPS_RLD_MAP -
538 	    DT_LOPROC + DT_NUM]);
539 #else
540 	map_link = NULL;
541 	for (dynp = exe_obj->load_dyn; dynp->d_tag; dynp++) {
542 		if (dynp->d_tag == DT_DEBUG) {
543 			map_link = (struct r_debug **)&dynp->d_un.d_ptr;
544 			break;
545 		}
546 	}
547 	if (dynp->d_tag != DT_DEBUG)
548 		DL_DEB(("failed to mark DTDEBUG\n"));
549 #endif
550 	if (map_link) {
551 		debug_map = (struct r_debug *)_dl_malloc(sizeof(*debug_map));
552 		debug_map->r_version = 1;
553 		debug_map->r_map = (struct link_map *)_dl_objects;
554 		debug_map->r_brk = (Elf_Addr)_dl_debug_state;
555 		debug_map->r_state = RT_CONSISTENT;
556 		debug_map->r_ldbase = dyn_loff;
557 		_dl_debug_map = debug_map;
558 		*map_link = _dl_debug_map;
559 	}
560 
561 	_dl_debug_state();
562 
563 	/*
564 	 * The first object is the executable itself,
565 	 * it is responsible for running it's own ctors/dtors
566 	 * thus do NOT run the ctors for the executable, all of
567 	 * the shared libraries which follow.
568 	 * Do not run init code if run from ldd.
569 	 */
570 	if (_dl_objects->next != NULL) {
571 		_dl_objects->status |= STAT_INIT_DONE;
572 		_dl_call_init(_dl_objects);
573 	}
574 
575 	/*
576 	 * Schedule a routine to be run at shutdown, by using atexit.
577 	 * Cannot call atexit directly from ld.so?
578 	 * Do not schedule destructors if run from ldd.
579 	 */
580 	{
581 		const elf_object_t *sobj;
582 		const Elf_Sym *sym;
583 		Elf_Addr ooff;
584 
585 		sym = NULL;
586 		ooff = _dl_find_symbol("atexit", &sym,
587 		    SYM_SEARCH_ALL|SYM_NOWARNNOTFOUND|SYM_PLT,
588 		    NULL, dyn_obj, &sobj);
589 		if (sym == NULL)
590 			_dl_printf("cannot find atexit, destructors will not be run!\n");
591 		else
592 #ifdef MD_ATEXIT
593 			MD_ATEXIT(sobj, sym, (Elf_Addr)&_dl_dtors);
594 #else
595 			(*(void (*)(Elf_Addr))(sym->st_value + ooff))
596 			    ((Elf_Addr)_dl_dtors);
597 #endif
598 	}
599 
600 	DL_DEB(("entry point: 0x%lx\n", dl_data[AUX_entry]));
601 
602 	/*
603 	 * Return the entry point.
604 	 */
605 	return(dl_data[AUX_entry]);
606 }
607 
608 void
609 _dl_boot_bind(const long sp, long *dl_data, Elf_Dyn *dynamicp)
610 {
611 	struct elf_object  dynld;	/* Resolver data for the loader */
612 	AuxInfo		*auxstack;
613 	long		*stack;
614 	Elf_Dyn		*dynp;
615 	int		n, argc;
616 	char **argv, **envp;
617 	long loff;
618 
619 	/*
620 	 * Scan argument and environment vectors. Find dynamic
621 	 * data vector put after them.
622 	 */
623 	stack = (long *)sp;
624 	argc = *stack++;
625 	argv = (char **)stack;
626 	envp = &argv[argc + 1];
627 	stack = (long *)envp;
628 	while (*stack++ != NULL)
629 		;
630 
631 	/*
632 	 * Zero out dl_data.
633 	 */
634 	for (n = 0; n <= AUX_entry; n++)
635 		dl_data[n] = 0;
636 
637 	/*
638 	 * Dig out auxiliary data set up by exec call. Move all known
639 	 * tags to an indexed local table for easy access.
640 	 */
641 	for (auxstack = (AuxInfo *)stack; auxstack->au_id != AUX_null;
642 	    auxstack++) {
643 		if (auxstack->au_id > AUX_entry)
644 			continue;
645 		dl_data[auxstack->au_id] = auxstack->au_v;
646 	}
647 	loff = dl_data[AUX_base];	/* XXX assumes ld.so is linked at 0x0 */
648 
649 	/*
650 	 * We need to do 'selfreloc' in case the code weren't
651 	 * loaded at the address it was linked to.
652 	 *
653 	 * Scan the DYNAMIC section for the loader.
654 	 * Cache the data for easier access.
655 	 */
656 
657 #if defined(__alpha__)
658 	dynp = (Elf_Dyn *)((long)_DYNAMIC);
659 #elif defined(__sparc__) || defined(__sparc64__) || defined(__powerpc__) || \
660     defined(__hppa__) || defined(__sh__)
661 	dynp = dynamicp;
662 #else
663 	dynp = (Elf_Dyn *)((long)_DYNAMIC + loff);
664 #endif
665 	while (dynp != NULL && dynp->d_tag != DT_NULL) {
666 		if (dynp->d_tag < DT_NUM)
667 			dynld.Dyn.info[dynp->d_tag] = dynp->d_un.d_val;
668 		else if (dynp->d_tag >= DT_LOPROC &&
669 		    dynp->d_tag < DT_LOPROC + DT_PROCNUM)
670 			dynld.Dyn.info[dynp->d_tag - DT_LOPROC + DT_NUM] =
671 			    dynp->d_un.d_val;
672 		if (dynp->d_tag == DT_TEXTREL)
673 			dynld.dyn.textrel = 1;
674 		dynp++;
675 	}
676 
677 	/*
678 	 * Do the 'bootstrap relocation'. This is really only needed if
679 	 * the code was loaded at another location than it was linked to.
680 	 * We don't do undefined symbols resolving (to difficult..)
681 	 */
682 
683 	/* "relocate" dyn.X values if they represent addresses */
684 	{
685 		int i, val;
686 		/* must be code, not pic data */
687 		int table[20];
688 
689 		i = 0;
690 		table[i++] = DT_PLTGOT;
691 		table[i++] = DT_HASH;
692 		table[i++] = DT_STRTAB;
693 		table[i++] = DT_SYMTAB;
694 		table[i++] = DT_RELA;
695 		table[i++] = DT_INIT;
696 		table[i++] = DT_FINI;
697 		table[i++] = DT_REL;
698 		table[i++] = DT_JMPREL;
699 		/* other processors insert their extras here */
700 		table[i++] = DT_NULL;
701 		for (i = 0; table[i] != DT_NULL; i++) {
702 			val = table[i];
703 			if (val > DT_HIPROC) /* ??? */
704 				continue;
705 			if (val > DT_LOPROC)
706 				val -= DT_LOPROC + DT_NUM;
707 			if (dynld.Dyn.info[val] != 0)
708 				dynld.Dyn.info[val] += loff;
709 		}
710 	}
711 
712 	{
713 		u_int32_t rs;
714 		Elf_Rel *rp;
715 		int	i;
716 
717 		rp = (Elf_Rel *)(dynld.Dyn.info[DT_REL]);
718 		rs = dynld.dyn.relsz;
719 
720 		for (i = 0; i < rs; i += sizeof (Elf_Rel)) {
721 			Elf_Addr *ra;
722 			const Elf_Sym *sp;
723 
724 			sp = dynld.dyn.symtab;
725 			sp += ELF_R_SYM(rp->r_info);
726 
727 			if (ELF_R_SYM(rp->r_info) && sp->st_value == 0) {
728 #if 0
729 /* cannot printf in this function */
730 				_dl_wrstderr("Dynamic loader failure: self bootstrapping impossible.\n");
731 				_dl_wrstderr("Undefined symbol: ");
732 				_dl_wrstderr((char *)dynld.dyn.strtab +
733 				    sp->st_name);
734 #endif
735 				_dl_exit(5);
736 			}
737 
738 			ra = (Elf_Addr *)(rp->r_offset + loff);
739 			RELOC_REL(rp, sp, ra, loff);
740 			rp++;
741 		}
742 	}
743 
744 	for (n = 0; n < 2; n++) {
745 		unsigned long rs;
746 		Elf_RelA *rp;
747 		int	i;
748 
749 		switch (n) {
750 		case 0:
751 			rp = (Elf_RelA *)(dynld.Dyn.info[DT_JMPREL]);
752 			rs = dynld.dyn.pltrelsz;
753 			break;
754 		case 1:
755 			rp = (Elf_RelA *)(dynld.Dyn.info[DT_RELA]);
756 			rs = dynld.dyn.relasz;
757 			break;
758 		default:
759 			rp = NULL;
760 			rs = 0;
761 		}
762 		for (i = 0; i < rs; i += sizeof (Elf_RelA)) {
763 			Elf_Addr *ra;
764 			const Elf_Sym *sp;
765 
766 			sp = dynld.dyn.symtab;
767 			sp += ELF_R_SYM(rp->r_info);
768 			if (ELF_R_SYM(rp->r_info) && sp->st_value == 0) {
769 #if 0
770 				_dl_wrstderr("Dynamic loader failure: self bootstrapping impossible.\n");
771 				_dl_wrstderr("Undefined symbol: ");
772 				_dl_wrstderr((char *)dynld.dyn.strtab +
773 				    sp->st_name);
774 #endif
775 				_dl_exit(6);
776 			}
777 
778 			ra = (Elf_Addr *)(rp->r_offset + loff);
779 			RELOC_RELA(rp, sp, ra, loff, dynld.dyn.pltgot);
780 			rp++;
781 		}
782 	}
783 
784 	RELOC_GOT(&dynld, loff);
785 
786 	/*
787 	 * we have been fully relocated here, so most things no longer
788 	 * need the loff adjustment
789 	 */
790 }
791 
792 #define DL_SM_SYMBUF_CNT 512
793 sym_cache _dl_sm_symcache_buffer[DL_SM_SYMBUF_CNT];
794 
795 int
796 _dl_rtld(elf_object_t *object)
797 {
798 	size_t sz;
799 	int fails = 0;
800 
801 	if (object->next)
802 		fails += _dl_rtld(object->next);
803 
804 	if (object->status & STAT_RELOC_DONE)
805 		return 0;
806 
807 	sz = 0;
808 	if (object->nchains < DL_SM_SYMBUF_CNT) {
809 		_dl_symcache = _dl_sm_symcache_buffer;
810 //		DL_DEB(("using static buffer for %d entries\n",
811 //		    object->nchains));
812 		_dl_memset(_dl_symcache, 0,
813 		    sizeof (sym_cache) * object->nchains);
814 	} else {
815 		sz = ELF_ROUND(sizeof (sym_cache) * object->nchains,
816 		    _dl_pagesz);
817 //		DL_DEB(("allocating symcache sz %x with mmap\n", sz));
818 
819 		_dl_symcache = (void *)_dl_mmap(0, sz, PROT_READ|PROT_WRITE,
820 		    MAP_PRIVATE|MAP_ANON, -1, 0);
821 		if (_dl_mmap_error(_dl_symcache)) {
822 			sz = 0;
823 			_dl_symcache = NULL;
824 		}
825 	}
826 	prebind_symcache(object, SYM_NOTPLT);
827 
828 	/*
829 	 * Do relocation information first, then GOT.
830 	 */
831 	fails =_dl_md_reloc(object, DT_REL, DT_RELSZ);
832 	fails += _dl_md_reloc(object, DT_RELA, DT_RELASZ);
833 	prebind_symcache(object, SYM_PLT);
834 	fails += _dl_md_reloc_got(object, !(_dl_bindnow ||
835 	    object->obj_flags & RTLD_NOW));
836 
837 	if (_dl_symcache != NULL) {
838 		if (sz != 0)
839 			_dl_munmap( _dl_symcache, sz);
840 		_dl_symcache = NULL;
841 	}
842 	if (fails == 0)
843 		object->status |= STAT_RELOC_DONE;
844 
845 	return (fails);
846 }
847 void
848 _dl_call_init(elf_object_t *object)
849 {
850 	struct dep_node *n;
851 
852 	TAILQ_FOREACH(n, &object->child_list, next_sib) {
853 		if (n->data->status & STAT_INIT_DONE)
854 			continue;
855 		_dl_call_init(n->data);
856 	}
857 
858 	if (object->status & STAT_INIT_DONE)
859 		return;
860 
861 	if (object->dyn.init) {
862 		DL_DEB(("doing ctors obj %p @%p: [%s]\n",
863 		    object, object->dyn.init, object->load_name));
864 		(*object->dyn.init)();
865 	}
866 
867 	/* What about loops? */
868 	object->status |= STAT_INIT_DONE;
869 }
870 
871 static char *
872 _dl_getenv(const char *var, char **env)
873 {
874 	const char *ep;
875 
876 	while ((ep = *env++)) {
877 		const char *vp = var;
878 
879 		while (*vp && *vp == *ep) {
880 			vp++;
881 			ep++;
882 		}
883 		if (*vp == '\0' && *ep++ == '=')
884 			return((char *)ep);
885 	}
886 	return(NULL);
887 }
888 
889 static void
890 _dl_unsetenv(const char *var, char **env)
891 {
892 	char *ep;
893 
894 	while ((ep = *env)) {
895 		const char *vp = var;
896 
897 		while (*vp && *vp == *ep) {
898 			vp++;
899 			ep++;
900 		}
901 		if (*vp == '\0' && *ep++ == '=') {
902 			char **P;
903 
904 			for (P = env;; ++P)
905 				if (!(*P = *(P + 1)))
906 					break;
907 		} else
908 			env++;
909 	}
910 }
911 
912 /*
913  * _dl_fixup_user_env()
914  *
915  * Set the user environment so that programs can use the environment
916  * while running constructors. Specifically, MALLOC_OPTIONS= for malloc()
917  */
918 void
919 _dl_fixup_user_env(void)
920 {
921 	const Elf_Sym *sym;
922 	Elf_Addr ooff;
923 	struct elf_object dummy_obj;
924 
925 	dummy_obj.dyn.symbolic = 0;
926 	dummy_obj.load_name = "ld.so";
927 
928 	sym = NULL;
929 	ooff = _dl_find_symbol("environ", &sym,
930 	    SYM_SEARCH_ALL|SYM_NOWARNNOTFOUND|SYM_PLT, NULL, &dummy_obj, NULL);
931 	if (sym != NULL)
932 		*((char ***)(sym->st_value + ooff)) = _dl_so_envp;
933 }
934