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