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