xref: /openbsd/libexec/ld.so/loader.c (revision e5dd7070)
1 /*	$OpenBSD: loader.c,v 1.190 2019/12/17 03:16:07 guenther Exp $ */
2 
3 /*
4  * Copyright (c) 1998 Per Fogelstrom, Opsycon AB
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  */
28 
29 #define	_DYN_LOADER
30 
31 #include <sys/types.h>
32 #include <sys/mman.h>
33 #include <sys/exec.h>
34 #include <sys/sysctl.h>
35 #include <nlist.h>
36 #include <string.h>
37 #include <link.h>
38 #include <limits.h>			/* NAME_MAX */
39 #include <dlfcn.h>
40 #include <tib.h>
41 
42 #include "syscall.h"
43 #include "archdep.h"
44 #include "path.h"
45 #include "resolve.h"
46 #include "sod.h"
47 #include "stdlib.h"
48 
49 /*
50  * Local decls.
51  */
52 unsigned long _dl_boot(const char **, char **, const long, long *) __boot;
53 void _dl_debug_state(void);
54 void _dl_setup_env(const char *_argv0, char **_envp) __boot;
55 void _dl_dtors(void);
56 void _dl_dopreload(char *_paths) __boot;
57 void _dl_fixup_user_env(void) __boot;
58 void _dl_call_preinit(elf_object_t *) __boot;
59 void _dl_call_init_recurse(elf_object_t *object, int initfirst);
60 void _dl_clean_boot(void);
61 static inline void unprotect_if_textrel(elf_object_t *_object);
62 static inline void reprotect_if_textrel(elf_object_t *_object);
63 
64 int _dl_pagesz __relro = 4096;
65 int _dl_bindnow __relro = 0;
66 int _dl_debug __relro = 0;
67 int _dl_trust __relro = 0;
68 char **_dl_libpath __relro = NULL;
69 const char **_dl_argv __relro = NULL;
70 int _dl_argc __relro = 0;
71 
72 char *_dl_preload __boot_data = NULL;
73 char *_dl_tracefmt1 __boot_data = NULL;
74 char *_dl_tracefmt2 __boot_data = NULL;
75 char *_dl_traceprog __boot_data = NULL;
76 
77 char **environ = NULL;
78 char *__progname = NULL;
79 
80 int _dl_traceld;
81 struct r_debug *_dl_debug_map;
82 
83 static dl_cb_cb _dl_cb_cb;
84 const struct dl_cb_0 callbacks_0 = {
85 	.dl_allocate_tib	= &_dl_allocate_tib,
86 	.dl_free_tib		= &_dl_free_tib,
87 #if DO_CLEAN_BOOT
88 	.dl_clean_boot		= &_dl_clean_boot,
89 #endif
90 	.dlopen			= &dlopen,
91 	.dlclose		= &dlclose,
92 	.dlsym			= &dlsym,
93 	.dladdr			= &dladdr,
94 	.dlctl			= &dlctl,
95 	.dlerror		= &dlerror,
96 	.dl_iterate_phdr	= &dl_iterate_phdr,
97 };
98 
99 
100 /*
101  * Run dtors for a single object.
102  */
103 void
104 _dl_run_dtors(elf_object_t *obj)
105 {
106 	if (obj->dyn.fini_array) {
107 		int num = obj->dyn.fini_arraysz / sizeof(Elf_Addr);
108 		int i;
109 
110 		DL_DEB(("doing finiarray obj %p @%p: [%s]\n",
111 		    obj, obj->dyn.fini_array, obj->load_name));
112 		for (i = num; i > 0; i--)
113 			(*obj->dyn.fini_array[i-1])();
114 	}
115 
116 	if (obj->dyn.fini) {
117 		DL_DEB(("doing dtors obj %p @%p: [%s]\n",
118 		    obj, obj->dyn.fini, obj->load_name));
119 		(*obj->dyn.fini)();
120 	}
121 }
122 
123 /*
124  * Run dtors for all objects that are eligible.
125  */
126 void
127 _dl_run_all_dtors(void)
128 {
129 	elf_object_t *node;
130 	int fini_complete;
131 	int skip_initfirst;
132 	int initfirst_skipped;
133 
134 	fini_complete = 0;
135 	skip_initfirst = 1;
136 	initfirst_skipped = 0;
137 
138 	while (fini_complete == 0) {
139 		fini_complete = 1;
140 		for (node = _dl_objects;
141 		    node != NULL;
142 		    node = node->next) {
143 			if ((node->dyn.fini || node->dyn.fini_array) &&
144 			    (OBJECT_REF_CNT(node) == 0) &&
145 			    (node->status & STAT_INIT_DONE) &&
146 			    ((node->status & STAT_FINI_DONE) == 0)) {
147 				if (skip_initfirst &&
148 				    (node->obj_flags & DF_1_INITFIRST))
149 					initfirst_skipped = 1;
150 				else
151 					node->status |= STAT_FINI_READY;
152 			    }
153 		}
154 		for (node = _dl_objects;
155 		    node != NULL;
156 		    node = node->next ) {
157 			if ((node->dyn.fini || node->dyn.fini_array) &&
158 			    (OBJECT_REF_CNT(node) == 0) &&
159 			    (node->status & STAT_INIT_DONE) &&
160 			    ((node->status & STAT_FINI_DONE) == 0) &&
161 			    (!skip_initfirst ||
162 			    (node->obj_flags & DF_1_INITFIRST) == 0)) {
163 				struct object_vector vec = node->child_vec;
164 				int i;
165 
166 				for (i = 0; i < vec.len; i++)
167 					vec.vec[i]->status &= ~STAT_FINI_READY;
168 			}
169 		}
170 
171 
172 		for (node = _dl_objects;
173 		    node != NULL;
174 		    node = node->next ) {
175 			if (node->status & STAT_FINI_READY) {
176 				fini_complete = 0;
177 				node->status |= STAT_FINI_DONE;
178 				node->status &= ~STAT_FINI_READY;
179 				_dl_run_dtors(node);
180 			}
181 		}
182 
183 		if (fini_complete && initfirst_skipped)
184 			fini_complete = initfirst_skipped = skip_initfirst = 0;
185 	}
186 }
187 
188 /*
189  * Routine to walk through all of the objects except the first
190  * (main executable).
191  *
192  * Big question, should dlopen()ed objects be unloaded before or after
193  * the destructor for the main application runs?
194  */
195 void
196 _dl_dtors(void)
197 {
198 	_dl_thread_kern_stop();
199 
200 	/* ORDER? */
201 	_dl_unload_dlopen();
202 
203 	DL_DEB(("doing dtors\n"));
204 
205 	_dl_objects->opencount--;
206 	_dl_notify_unload_shlib(_dl_objects);
207 
208 	_dl_run_all_dtors();
209 }
210 
211 #if DO_CLEAN_BOOT
212 void
213 _dl_clean_boot(void)
214 {
215 	extern char boot_text_start[], boot_text_end[];
216 #if 0	/* XXX breaks boehm-gc?!? */
217 	extern char boot_data_start[], boot_data_end[];
218 #endif
219 
220 	_dl_munmap(boot_text_start, boot_text_end - boot_text_start);
221 #if 0	/* XXX breaks boehm-gc?!? */
222 	_dl_munmap(boot_data_start, boot_data_end - boot_data_start);
223 #endif
224 }
225 #endif /* DO_CLEAN_BOOT */
226 
227 void
228 _dl_dopreload(char *paths)
229 {
230 	char		*cp, *dp;
231 	elf_object_t	*shlib;
232 	int		count;
233 
234 	dp = paths = _dl_strdup(paths);
235 	if (dp == NULL)
236 		_dl_oom();
237 
238 	/* preallocate child_vec for the LD_PRELOAD objects */
239 	count = 1;
240 	while (*dp++ != '\0')
241 		if (*dp == ':')
242 			count++;
243 	object_vec_grow(&_dl_objects->child_vec, count);
244 
245 	dp = paths;
246 	while ((cp = _dl_strsep(&dp, ":")) != NULL) {
247 		shlib = _dl_load_shlib(cp, _dl_objects, OBJTYPE_LIB,
248 		    _dl_objects->obj_flags);
249 		if (shlib == NULL)
250 			_dl_die("can't preload library '%s'", cp);
251 		_dl_add_object(shlib);
252 		_dl_link_child(shlib, _dl_objects);
253 	}
254 	_dl_free(paths);
255 	return;
256 }
257 
258 /*
259  * grab interesting environment variables, zap bad env vars if
260  * issetugid, and set the exported environ and __progname variables
261  */
262 void
263 _dl_setup_env(const char *argv0, char **envp)
264 {
265 	static char progname_storage[NAME_MAX+1] = "";
266 
267 	/*
268 	 * Don't allow someone to change the search paths if he runs
269 	 * a suid program without credentials high enough.
270 	 */
271 	_dl_trust = !_dl_issetugid();
272 	if (!_dl_trust) {	/* Zap paths if s[ug]id... */
273 		_dl_unsetenv("LD_DEBUG", envp);
274 		_dl_unsetenv("LD_LIBRARY_PATH", envp);
275 		_dl_unsetenv("LD_PRELOAD", envp);
276 		_dl_unsetenv("LD_BIND_NOW", envp);
277 	} else {
278 		/*
279 		 * Get paths to various things we are going to use.
280 		 */
281 		_dl_debug = _dl_getenv("LD_DEBUG", envp) != NULL;
282 		_dl_libpath = _dl_split_path(_dl_getenv("LD_LIBRARY_PATH",
283 		    envp));
284 		_dl_preload = _dl_getenv("LD_PRELOAD", envp);
285 		_dl_bindnow = _dl_getenv("LD_BIND_NOW", envp) != NULL;
286 	}
287 
288 	/* these are usable even in setugid processes */
289 	_dl_traceld = _dl_getenv("LD_TRACE_LOADED_OBJECTS", envp) != NULL;
290 	_dl_tracefmt1 = _dl_getenv("LD_TRACE_LOADED_OBJECTS_FMT1", envp);
291 	_dl_tracefmt2 = _dl_getenv("LD_TRACE_LOADED_OBJECTS_FMT2", envp);
292 	_dl_traceprog = _dl_getenv("LD_TRACE_LOADED_OBJECTS_PROGNAME", envp);
293 
294 	environ = envp;
295 
296 	_dl_trace_setup(envp);
297 
298 	if (argv0 != NULL) {		/* NULL ptr if argc = 0 */
299 		const char *p = _dl_strrchr(argv0, '/');
300 
301 		if (p == NULL)
302 			p = argv0;
303 		else
304 			p++;
305 		_dl_strlcpy(progname_storage, p, sizeof(progname_storage));
306 	}
307 	__progname = progname_storage;
308 }
309 
310 int
311 _dl_load_dep_libs(elf_object_t *object, int flags, int booting)
312 {
313 	elf_object_t *dynobj;
314 	Elf_Dyn *dynp;
315 	unsigned int loop;
316 	int libcount;
317 	int depflags;
318 
319 	dynobj = object;
320 	while (dynobj) {
321 		DL_DEB(("examining: '%s'\n", dynobj->load_name));
322 		libcount = 0;
323 
324 		/* propagate DF_1_NOW to deplibs (can be set by dynamic tags) */
325 		depflags = flags | (dynobj->obj_flags & DF_1_NOW);
326 
327 		for (dynp = dynobj->load_dyn; dynp->d_tag; dynp++) {
328 			if (dynp->d_tag == DT_NEEDED) {
329 				libcount++;
330 			}
331 		}
332 
333 		if ( libcount != 0) {
334 			struct listent {
335 				Elf_Dyn *dynp;
336 				elf_object_t *depobj;
337 			} *liblist;
338 			int *randomlist;
339 
340 			liblist = _dl_reallocarray(NULL, libcount,
341 			    sizeof(struct listent));
342 			randomlist =  _dl_reallocarray(NULL, libcount,
343 			    sizeof(int));
344 
345 			if (liblist == NULL || randomlist == NULL)
346 				_dl_oom();
347 
348 			for (dynp = dynobj->load_dyn, loop = 0; dynp->d_tag;
349 			    dynp++)
350 				if (dynp->d_tag == DT_NEEDED)
351 					liblist[loop++].dynp = dynp;
352 
353 			/* Randomize these */
354 			for (loop = 0; loop < libcount; loop++)
355 				randomlist[loop] = loop;
356 
357 			for (loop = 1; loop < libcount; loop++) {
358 				unsigned int rnd;
359 				int cur;
360 				rnd = _dl_arc4random();
361 				rnd = rnd % (loop+1);
362 				cur = randomlist[rnd];
363 				randomlist[rnd] = randomlist[loop];
364 				randomlist[loop] = cur;
365 			}
366 
367 			for (loop = 0; loop < libcount; loop++) {
368 				elf_object_t *depobj;
369 				const char *libname;
370 				libname = dynobj->dyn.strtab;
371 				libname +=
372 				    liblist[randomlist[loop]].dynp->d_un.d_val;
373 				DL_DEB(("loading: %s required by %s\n", libname,
374 				    dynobj->load_name));
375 				depobj = _dl_load_shlib(libname, dynobj,
376 				    OBJTYPE_LIB, depflags);
377 				if (depobj == 0) {
378 					if (booting) {
379 						_dl_die(
380 						    "can't load library '%s'",
381 						    libname);
382 					}
383 					DL_DEB(("dlopen: failed to open %s\n",
384 					    libname));
385 					_dl_free(liblist);
386 					_dl_free(randomlist);
387 					return (1);
388 				}
389 				liblist[randomlist[loop]].depobj = depobj;
390 			}
391 
392 			object_vec_grow(&dynobj->child_vec, libcount);
393 			for (loop = 0; loop < libcount; loop++) {
394 				_dl_add_object(liblist[loop].depobj);
395 				_dl_link_child(liblist[loop].depobj, dynobj);
396 			}
397 			_dl_free(liblist);
398 			_dl_free(randomlist);
399 		}
400 		dynobj = dynobj->next;
401 	}
402 
403 	_dl_cache_grpsym_list_setup(object);
404 
405 	return(0);
406 }
407 
408 
409 /* do any RWX -> RX fixups for executable PLTs and apply GNU_RELRO */
410 static inline void
411 _dl_self_relro(long loff)
412 {
413 	Elf_Ehdr *ehdp;
414 	Elf_Phdr *phdp;
415 	int i;
416 
417 	ehdp = (Elf_Ehdr *)loff;
418 	phdp = (Elf_Phdr *)(loff + ehdp->e_phoff);
419 	for (i = 0; i < ehdp->e_phnum; i++, phdp++) {
420 		switch (phdp->p_type) {
421 #if defined(__alpha__) || defined(__hppa__) || defined(__powerpc__) || \
422     defined(__sparc64__)
423 		case PT_LOAD:
424 			if ((phdp->p_flags & (PF_X | PF_W)) != (PF_X | PF_W))
425 				break;
426 			_dl_mprotect((void *)(phdp->p_vaddr + loff),
427 			    phdp->p_memsz, PROT_READ);
428 			break;
429 #endif
430 		case PT_GNU_RELRO:
431 			_dl_mprotect((void *)(phdp->p_vaddr + loff),
432 			    phdp->p_memsz, PROT_READ);
433 			break;
434 		}
435 	}
436 }
437 
438 
439 #define PFLAGS(X) ((((X) & PF_R) ? PROT_READ : 0) | \
440 		   (((X) & PF_W) ? PROT_WRITE : 0) | \
441 		   (((X) & PF_X) ? PROT_EXEC : 0))
442 
443 /*
444  * This is the dynamic loader entrypoint. When entering here, depending
445  * on architecture type, the stack and registers are set up according
446  * to the architectures ABI specification. The first thing required
447  * to do is to dig out all information we need to accomplish our task.
448  */
449 unsigned long
450 _dl_boot(const char **argv, char **envp, const long dyn_loff, long *dl_data)
451 {
452 	struct elf_object *exe_obj;	/* Pointer to executable object */
453 	struct elf_object *dyn_obj;	/* Pointer to ld.so object */
454 	struct r_debug **map_link;	/* Where to put pointer for gdb */
455 	struct r_debug *debug_map;
456 	struct load_list *next_load, *load_list = NULL;
457 	Elf_Dyn *dynp;
458 	Elf_Phdr *phdp;
459 	Elf_Ehdr *ehdr;
460 	char *us = NULL;
461 	unsigned int loop;
462 	int failed;
463 	struct dep_node *n;
464 	Elf_Addr minva, maxva, exe_loff;
465 	Elf_Phdr *ptls = NULL;
466 	int align;
467 
468 	if (dl_data[AUX_pagesz] != 0)
469 		_dl_pagesz = dl_data[AUX_pagesz];
470 	_dl_malloc_init();
471 
472 	_dl_argv = argv;
473 	while (_dl_argv[_dl_argc] != NULL)
474 		_dl_argc++;
475 	_dl_setup_env(argv[0], envp);
476 
477 	/*
478 	 * Make read-only the GOT and PLT and variables initialized
479 	 * during the ld.so setup above.
480 	 */
481 	_dl_self_relro(dyn_loff);
482 
483 	align = _dl_pagesz - 1;
484 
485 #define ROUND_PG(x) (((x) + align) & ~(align))
486 #define TRUNC_PG(x) ((x) & ~(align))
487 
488 	if (_dl_bindnow) {
489 		/* Lazy binding disabled, so disable kbind */
490 		_dl___syscall(SYS_kbind, (void *)NULL, (size_t)0, (long long)0);
491 	}
492 
493 	DL_DEB(("ld.so loading: '%s'\n", __progname));
494 
495 	/* init this in runtime, not statically */
496 	TAILQ_INIT(&_dlopened_child_list);
497 
498 	exe_obj = NULL;
499 	_dl_loading_object = NULL;
500 
501 	minva = ELF_NO_ADDR;
502 	maxva = exe_loff = 0;
503 
504 	/*
505 	 * Examine the user application and set up object information.
506 	 */
507 	phdp = (Elf_Phdr *)dl_data[AUX_phdr];
508 	for (loop = 0; loop < dl_data[AUX_phnum]; loop++) {
509 		switch (phdp->p_type) {
510 		case PT_PHDR:
511 			exe_loff = (Elf_Addr)dl_data[AUX_phdr] - phdp->p_vaddr;
512 			us += exe_loff;
513 			DL_DEB(("exe load offset:  0x%lx\n", exe_loff));
514 			break;
515 		case PT_DYNAMIC:
516 			minva = TRUNC_PG(minva);
517 			maxva = ROUND_PG(maxva);
518 			exe_obj = _dl_finalize_object(argv[0] ? argv[0] : "",
519 			    (Elf_Dyn *)(phdp->p_vaddr + exe_loff),
520 			    (Elf_Phdr *)dl_data[AUX_phdr],
521 			    dl_data[AUX_phnum], OBJTYPE_EXE, minva + exe_loff,
522 			    exe_loff);
523 			_dl_add_object(exe_obj);
524 			break;
525 		case PT_INTERP:
526 			us += phdp->p_vaddr;
527 			break;
528 		case PT_LOAD:
529 			if (phdp->p_vaddr < minva)
530 				minva = phdp->p_vaddr;
531 			if (phdp->p_vaddr > maxva)
532 				maxva = phdp->p_vaddr + phdp->p_memsz;
533 
534 			next_load = _dl_calloc(1, sizeof(struct load_list));
535 			if (next_load == NULL)
536 				_dl_oom();
537 			next_load->next = load_list;
538 			load_list = next_load;
539 			next_load->start = (char *)TRUNC_PG(phdp->p_vaddr) + exe_loff;
540 			next_load->size = (phdp->p_vaddr & align) + phdp->p_filesz;
541 			next_load->prot = PFLAGS(phdp->p_flags);
542 			break;
543 		case PT_TLS:
544 			if (phdp->p_filesz > phdp->p_memsz)
545 				_dl_die("invalid tls data");
546 			ptls = phdp;
547 			break;
548 		case PT_GNU_RELRO:
549 			exe_obj->relro_addr = phdp->p_vaddr + exe_loff;
550 			exe_obj->relro_size = phdp->p_memsz;
551 			break;
552 		}
553 		phdp++;
554 	}
555 	exe_obj->load_list = load_list;
556 	exe_obj->obj_flags |= DF_1_GLOBAL;
557 	exe_obj->load_size = maxva - minva;
558 	_dl_set_sod(exe_obj->load_name, &exe_obj->sod);
559 
560 	/* TLS bits in the base executable */
561 	if (ptls != NULL && ptls->p_memsz)
562 		_dl_set_tls(exe_obj, ptls, exe_loff, NULL);
563 
564 	n = _dl_malloc(sizeof *n);
565 	if (n == NULL)
566 		_dl_oom();
567 	n->data = exe_obj;
568 	TAILQ_INSERT_TAIL(&_dlopened_child_list, n, next_sib);
569 	exe_obj->opencount++;
570 
571 	if (_dl_preload != NULL)
572 		_dl_dopreload(_dl_preload);
573 
574 	_dl_load_dep_libs(exe_obj, exe_obj->obj_flags, 1);
575 
576 	/*
577 	 * Now add the dynamic loader itself last in the object list
578 	 * so we can use the _dl_ code when serving dl.... calls.
579 	 * Intentionally left off the exe child_vec.
580 	 */
581 	dynp = (Elf_Dyn *)((void *)_DYNAMIC);
582 	ehdr = (Elf_Ehdr *)dl_data[AUX_base];
583 	dyn_obj = _dl_finalize_object(us, dynp,
584 	    (Elf_Phdr *)((char *)dl_data[AUX_base] + ehdr->e_phoff),
585 	    ehdr->e_phnum, OBJTYPE_LDR, dl_data[AUX_base], dyn_loff);
586 	_dl_add_object(dyn_obj);
587 
588 	dyn_obj->refcount++;
589 	_dl_link_grpsym(dyn_obj);
590 
591 	dyn_obj->status |= STAT_RELOC_DONE;
592 	_dl_set_sod(dyn_obj->load_name, &dyn_obj->sod);
593 
594 	/* calculate the offsets for static TLS allocations */
595 	_dl_allocate_tls_offsets();
596 
597 	/*
598 	 * Make something to help gdb when poking around in the code.
599 	 * Do this poking at the .dynamic section now, before relocation
600 	 * renders it read-only
601 	 */
602 	map_link = NULL;
603 #ifdef __mips__
604 	if (exe_obj->Dyn.info[DT_MIPS_RLD_MAP - DT_LOPROC + DT_NUM] != 0)
605 		map_link = (struct r_debug **)(exe_obj->Dyn.info[
606 		    DT_MIPS_RLD_MAP - DT_LOPROC + DT_NUM] + exe_loff);
607 #endif
608 	if (map_link == NULL) {
609 		for (dynp = exe_obj->load_dyn; dynp->d_tag; dynp++) {
610 			if (dynp->d_tag == DT_DEBUG) {
611 				map_link = (struct r_debug **)&dynp->d_un.d_ptr;
612 				break;
613 			}
614 		}
615 		if (dynp->d_tag != DT_DEBUG)
616 			DL_DEB(("failed to mark DTDEBUG\n"));
617 	}
618 	if (map_link) {
619 		debug_map = _dl_malloc(sizeof(*debug_map));
620 		if (debug_map == NULL)
621 			_dl_oom();
622 		debug_map->r_version = 1;
623 		debug_map->r_map = (struct link_map *)_dl_objects;
624 		debug_map->r_brk = (Elf_Addr)_dl_debug_state;
625 		debug_map->r_state = RT_CONSISTENT;
626 		debug_map->r_ldbase = dyn_loff;
627 		_dl_debug_map = debug_map;
628 #ifdef __mips__
629 		Elf_Addr relro_addr = exe_obj->relro_addr;
630 		if (dynp->d_tag == DT_DEBUG &&
631 		    ((Elf_Addr)map_link + sizeof(*map_link) <= relro_addr ||
632 		     (Elf_Addr)map_link >= relro_addr + exe_obj->relro_size)) {
633 			_dl_mprotect(map_link, sizeof(*map_link),
634 			    PROT_READ|PROT_WRITE);
635 			*map_link = _dl_debug_map;
636 			_dl_mprotect(map_link, sizeof(*map_link),
637 			    PROT_READ|PROT_EXEC);
638 		} else
639 #endif
640 			*map_link = _dl_debug_map;
641 	}
642 
643 
644 	/*
645 	 * Everything should be in place now for doing the relocation
646 	 * and binding. Call _dl_rtld to do the job. Fingers crossed.
647 	 */
648 
649 	failed = 0;
650 	if (!_dl_traceld)
651 		failed = _dl_rtld(_dl_objects);
652 
653 	if (_dl_debug || _dl_traceld) {
654 		if (_dl_traceld)
655 			_dl_pledge("stdio rpath", NULL);
656 		_dl_show_objects();
657 	}
658 
659 	DL_DEB(("dynamic loading done, %s.\n",
660 	    (failed == 0) ? "success":"failed"));
661 
662 	if (failed != 0)
663 		_dl_die("relocation failed");
664 
665 	if (_dl_traceld)
666 		_dl_exit(0);
667 
668 	_dl_loading_object = NULL;
669 
670 	/* set up the TIB for the initial thread */
671 	_dl_allocate_first_tib();
672 
673 	_dl_fixup_user_env();
674 
675 	_dl_debug_state();
676 
677 	/*
678 	 * Do not run init code if run from ldd.
679 	 */
680 	if (_dl_objects->next != NULL) {
681 		_dl_call_preinit(_dl_objects);
682 		_dl_call_init(_dl_objects);
683 	}
684 
685 	DL_DEB(("entry point: 0x%lx\n", dl_data[AUX_entry]));
686 
687 	/*
688 	 * Return the entry point.
689 	 */
690 	return(dl_data[AUX_entry]);
691 }
692 
693 int
694 _dl_rtld(elf_object_t *object)
695 {
696 	struct load_list *llist;
697 	int fails = 0;
698 
699 	if (object->next)
700 		fails += _dl_rtld(object->next);
701 
702 	if (object->status & STAT_RELOC_DONE)
703 		return 0;
704 
705 	/*
706 	 * Do relocation information first, then GOT.
707 	 */
708 	unprotect_if_textrel(object);
709 	fails =_dl_md_reloc(object, DT_REL, DT_RELSZ);
710 	fails += _dl_md_reloc(object, DT_RELA, DT_RELASZ);
711 	reprotect_if_textrel(object);
712 
713 	/*
714 	 * We do lazy resolution by default, doing eager resolution if
715 	 *  - the object requests it with -znow, OR
716 	 *  - LD_BIND_NOW is set and this object isn't being ltraced
717 	 *
718 	 * Note that -znow disables ltrace for the object: on at least
719 	 * amd64 'ld' doesn't generate the trampoline for lazy relocation
720 	 * when -znow is used.
721 	 */
722 	fails += _dl_md_reloc_got(object, !(object->obj_flags & DF_1_NOW) &&
723 	    !(_dl_bindnow && !object->traced));
724 
725 	/*
726 	 * Look for W&X segments and make them read-only.
727 	 */
728 	for (llist = object->load_list; llist != NULL; llist = llist->next) {
729 		if ((llist->prot & PROT_WRITE) && (llist->prot & PROT_EXEC)) {
730 			_dl_mprotect(llist->start, llist->size,
731 			    llist->prot & ~PROT_WRITE);
732 		}
733 	}
734 
735 	if (fails == 0)
736 		object->status |= STAT_RELOC_DONE;
737 
738 	return (fails);
739 }
740 
741 void
742 _dl_call_preinit(elf_object_t *object)
743 {
744 	if (object->dyn.preinit_array) {
745 		int num = object->dyn.preinit_arraysz / sizeof(Elf_Addr);
746 		int i;
747 
748 		DL_DEB(("doing preinitarray obj %p @%p: [%s]\n",
749 		    object, object->dyn.preinit_array, object->load_name));
750 		for (i = 0; i < num; i++)
751 			(*object->dyn.preinit_array[i])(_dl_argc, _dl_argv,
752 			    environ, &_dl_cb_cb);
753 	}
754 }
755 
756 void
757 _dl_call_init(elf_object_t *object)
758 {
759 	_dl_call_init_recurse(object, 1);
760 	_dl_call_init_recurse(object, 0);
761 }
762 
763 static void
764 _dl_relro(elf_object_t *object)
765 {
766 	/*
767 	 * Handle GNU_RELRO
768 	 */
769 	if (object->relro_addr != 0 && object->relro_size != 0) {
770 		Elf_Addr addr = object->relro_addr;
771 
772 		DL_DEB(("protect RELRO [0x%lx,0x%lx) in %s\n",
773 		    addr, addr + object->relro_size, object->load_name));
774 		_dl_mprotect((void *)addr, object->relro_size, PROT_READ);
775 	}
776 }
777 
778 void
779 _dl_call_init_recurse(elf_object_t *object, int initfirst)
780 {
781 	struct object_vector vec;
782 	int visited_flag = initfirst ? STAT_VISIT_INITFIRST : STAT_VISIT_INIT;
783 	int i;
784 
785 	object->status |= visited_flag;
786 
787 	for (vec = object->child_vec, i = 0; i < vec.len; i++) {
788 		if (vec.vec[i]->status & visited_flag)
789 			continue;
790 		_dl_call_init_recurse(vec.vec[i], initfirst);
791 	}
792 
793 	if (object->status & STAT_INIT_DONE)
794 		return;
795 
796 	if (initfirst && (object->obj_flags & DF_1_INITFIRST) == 0)
797 		return;
798 
799 	if (!initfirst)
800 		_dl_relro(object);
801 
802 	if (object->dyn.init) {
803 		DL_DEB(("doing ctors obj %p @%p: [%s]\n",
804 		    object, object->dyn.init, object->load_name));
805 		(*object->dyn.init)();
806 	}
807 
808 	if (object->dyn.init_array) {
809 		int num = object->dyn.init_arraysz / sizeof(Elf_Addr);
810 		int i;
811 
812 		DL_DEB(("doing initarray obj %p @%p: [%s]\n",
813 		    object, object->dyn.init_array, object->load_name));
814 		for (i = 0; i < num; i++)
815 			(*object->dyn.init_array[i])(_dl_argc, _dl_argv,
816 			    environ, &_dl_cb_cb);
817 	}
818 
819 	if (initfirst)
820 		_dl_relro(object);
821 
822 	object->status |= STAT_INIT_DONE;
823 }
824 
825 char *
826 _dl_getenv(const char *var, char **env)
827 {
828 	const char *ep;
829 
830 	while ((ep = *env++)) {
831 		const char *vp = var;
832 
833 		while (*vp && *vp == *ep) {
834 			vp++;
835 			ep++;
836 		}
837 		if (*vp == '\0' && *ep++ == '=')
838 			return((char *)ep);
839 	}
840 	return(NULL);
841 }
842 
843 void
844 _dl_unsetenv(const char *var, char **env)
845 {
846 	char *ep;
847 
848 	while ((ep = *env)) {
849 		const char *vp = var;
850 
851 		while (*vp && *vp == *ep) {
852 			vp++;
853 			ep++;
854 		}
855 		if (*vp == '\0' && *ep++ == '=') {
856 			char **P;
857 
858 			for (P = env;; ++P)
859 				if (!(*P = *(P + 1)))
860 					break;
861 		} else
862 			env++;
863 	}
864 }
865 
866 static inline void
867 fixup_sym(struct elf_object *dummy_obj, const char *name, void *addr)
868 {
869 	struct sym_res sr;
870 
871 	sr = _dl_find_symbol(name, SYM_SEARCH_ALL|SYM_NOWARNNOTFOUND|SYM_PLT,
872 	    NULL, dummy_obj);
873 	if (sr.sym != NULL) {
874 		void *p = (void *)(sr.sym->st_value + sr.obj->obj_base);
875 		if (p != addr) {
876 			DL_DEB(("setting %s %p@%s[%p] from %p\n", name,
877 			    p, sr.obj->load_name, (void *)sr.obj, addr));
878 			*(void **)p = *(void **)addr;
879 		}
880 	}
881 }
882 
883 /*
884  * _dl_fixup_user_env()
885  *
886  * Set the user environment so that programs can use the environment
887  * while running constructors. Specifically, MALLOC_OPTIONS= for malloc()
888  */
889 void
890 _dl_fixup_user_env(void)
891 {
892 	struct elf_object dummy_obj;
893 
894 	dummy_obj.dyn.symbolic = 0;
895 	dummy_obj.load_name = "ld.so";
896 	fixup_sym(&dummy_obj, "environ", &environ);
897 	fixup_sym(&dummy_obj, "__progname", &__progname);
898 }
899 
900 const void *
901 _dl_cb_cb(int version)
902 {
903 	DL_DEB(("version %d callbacks requested\n", version));
904 	if (version == 0)
905 		return &callbacks_0;
906 	return NULL;
907 }
908 
909 static inline void
910 unprotect_if_textrel(elf_object_t *object)
911 {
912 	struct load_list *ll;
913 
914 	if (__predict_false(object->dyn.textrel == 1)) {
915 		for (ll = object->load_list; ll != NULL; ll = ll->next) {
916 			if ((ll->prot & PROT_WRITE) == 0)
917 				_dl_mprotect(ll->start, ll->size,
918 				    PROT_READ | PROT_WRITE);
919 		}
920 	}
921 }
922 
923 static inline void
924 reprotect_if_textrel(elf_object_t *object)
925 {
926 	struct load_list *ll;
927 
928 	if (__predict_false(object->dyn.textrel == 1)) {
929 		for (ll = object->load_list; ll != NULL; ll = ll->next) {
930 			if ((ll->prot & PROT_WRITE) == 0)
931 				_dl_mprotect(ll->start, ll->size, ll->prot);
932 		}
933 	}
934 }
935