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