xref: /openbsd-src/libexec/ld.so/loader.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: loader.c,v 1.17 2001/06/13 08:40:39 art 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  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *	This product includes software developed under OpenBSD by
17  *	Per Fogelstrom, Opsycon AB, Sweden.
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
22  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
25  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  */
34 
35 #define	_DYN_LOADER
36 
37 #include <sys/types.h>
38 #include <sys/mman.h>
39 #include <sys/exec.h>
40 #include <nlist.h>
41 #include <link.h>
42 
43 #include "syscall.h"
44 #include "archdep.h"
45 #include "resolve.h"
46 
47 /*
48  *  Local decls.
49  */
50 static char *_dl_getenv(const char *var, const char **env);
51 
52 /*
53  * Static vars usable after bootsrapping.
54  */
55 static void *_dl_malloc_base;
56 static void *_dl_malloc_pool = 0;
57 static long *_dl_malloc_free = 0;
58 
59 const char *_dl_progname;
60 int  _dl_pagesz;
61 int  _dl_trusted;
62 
63 char *_dl_libpath;
64 char *_dl_preload;
65 char *_dl_bindnow;
66 char *_dl_traceld;
67 char *_dl_debug;
68 char *_dl_showmap;
69 
70 struct r_debug *_dl_debug_map;
71 void _dl_unmaphints();
72 
73 void
74 _dl_debug_state(void)
75 {
76 	/* Debugger stub */
77 }
78 
79 /*
80  * Routine to walk thru all of the objects except the first (main executable).
81  */
82 
83 void
84 _dl_run_dtors(elf_object_t *object)
85 {
86 	DL_DEB(("doing dtors: [%s]\n", object->load_name));
87 	if (object->dyn.fini) {
88 		(*object->dyn.fini)();
89 	}
90 	if (object->next) {
91 		_dl_run_dtors(object->next);
92 	}
93 }
94 
95 void
96 _dl_dtors(void)
97 {
98 	DL_DEB(("doing dtors\n"));
99 	if (_dl_objects->next) {
100 		_dl_run_dtors(_dl_objects->next);
101 	}
102 }
103 
104 /*
105  *  This is the dynamic loader entrypoint. When entering here, depending
106  *  on architecture type, the stack and registers are set up according
107  *  to the architectures ABI specification. The first thing required
108  *  to do is to dig out all information we need to accomplish out task.
109  */
110 unsigned long
111 _dl_boot(const char **argv, const char **envp, const long loff,
112 	Elf_Dyn *dynp, long *dl_data)
113 {
114 	int		n;
115 	int		brk_addr;
116 	Elf_Phdr	*phdp;
117 	char		*us = "";
118 	elf_object_t	*dynobj;
119 	struct elf_object  *exe_obj;	/* Pointer to executable object */
120 	struct elf_object  *dyn_obj;	/* Pointer to executable object */
121 	struct r_debug * debug_map;
122 #ifdef __mips__
123 	struct r_debug	   **map_link;	/* Where to put pointer for gdb */
124 #endif /* __mips__ */
125 
126 	/*
127 	 *  Get paths to various things we are going to use.
128 	 */
129 
130 	_dl_libpath = _dl_getenv("LD_LIBRARY_PATH", envp);
131 	_dl_preload = _dl_getenv("LD_PRELOAD", envp);
132 	_dl_bindnow = _dl_getenv("LD_BIND_NOW", envp);
133 	_dl_traceld = _dl_getenv("LD_TRACE_LOADED_OBJECTS", envp);
134 	_dl_debug   = _dl_getenv("LD_DEBUG", envp);
135 
136 	_dl_progname = argv[0];
137 	if (dl_data[AUX_pagesz] != 0) {
138 		_dl_pagesz = dl_data[AUX_pagesz];
139 	} else {
140 		_dl_pagesz = 4096;
141 	}
142 	DL_DEB(("rtld loading: '%s'\n", _dl_progname));
143 
144 	/*
145 	 *  Don't allow someone to change the search paths if he runs
146 	 *  a suid program without credentials high enough.
147 	 */
148 	if ((_dl_trusted = !_dl_suid_ok())) {	/* Zap paths if s[ug]id... */
149 		if (_dl_preload) {
150 			*_dl_preload = '\0';
151 		}
152 		if (_dl_libpath) {
153 			*_dl_libpath = '\0';
154 		}
155 	}
156 
157 	/*
158 	 *  Examine the user application and set up object information.
159 	 */
160 	phdp = (Elf_Phdr *)dl_data[AUX_phdr];
161 	for (n = 0; n < dl_data[AUX_phnum]; n++) {
162 		if (phdp->p_type == PT_LOAD) {				/*XXX*/
163 			if (phdp->p_vaddr + phdp->p_memsz > brk_addr)	/*XXX*/
164 				brk_addr = phdp->p_vaddr + phdp->p_memsz;
165 		}							/*XXX*/
166 		if (phdp->p_type == PT_DYNAMIC) {
167 			exe_obj = _dl_add_object("", (Elf_Dyn *)phdp->p_vaddr,
168 						   dl_data, OBJTYPE_EXE, 0, 0);
169 		}
170 		if (phdp->p_type == PT_INTERP) {
171 			us = (char *)_dl_malloc(_dl_strlen((char *)phdp->p_vaddr) + 1);
172 			_dl_strcpy(us, (char *)phdp->p_vaddr);
173 		}
174 		phdp++;
175 	}
176 
177 	/*
178 	 *  Now, pick up and 'load' all libraries requierd. Start
179 	 *  With the first on the list and then do whatever gets
180 	 *  added along the tour.
181 	 */
182 
183 	dynobj = _dl_objects;
184 	while (dynobj) {
185 		DL_DEB(("examining: '%s'\n", dynobj->load_name));
186 		for (dynp = dynobj->load_dyn; dynp->d_tag; dynp++) {
187 			const char *libname;
188 
189 			if (dynp->d_tag != DT_NEEDED)
190 				continue;
191 			libname = dynobj->dyn.strtab;
192 			libname += dynp->d_un.d_val;
193 			DL_DEB(("needs: '%s'\n", libname));
194 			if (_dl_load_shlib(libname, dynobj, OBJTYPE_LIB) == 0) {
195 				_dl_printf("%s: can't load library '%s'\n",
196 					_dl_progname, libname);
197 				_dl_exit(4);
198 			}
199 		}
200 		dynobj = dynobj->next;
201 	}
202 
203 	/*
204 	 * Now add the dynamic loader itself last in the object list
205 	 * so we can use the _dl_ code when serving dl.... calls.
206 	 */
207 
208 	dynp = (Elf_Dyn *)((void *)_DYNAMIC);
209 	dyn_obj = _dl_add_object(us, dynp, 0, OBJTYPE_LDR, dl_data[AUX_base], loff);
210 	dyn_obj->status |= STAT_RELOC_DONE;
211 
212 	/*
213 	 *  Everything should be in place now for doing the relocation
214 	 *  and binding. Call _dl_rtld to do the job. Fingers crossed.
215 	 */
216 
217 	_dl_rtld(_dl_objects);
218 
219 	/*
220 	 * The first object is the executable itself,
221 	 * it is responsible for running it's own ctors/dtors
222 	 * thus do NOT run the ctors for the executable, all of
223 	 * the shared libraries which follow.
224 	 */
225 	if (_dl_objects->next) {
226 		_dl_call_init(_dl_objects->next);
227 	}
228 
229 	/*
230 	 * Schedule a routine to be run at shutdown, by using atexit.
231 	 * cannot call atexit directly from ld.so?
232 	 */
233 	{
234 		const Elf_Sym  *sym;
235 		Elf_Addr ooff;
236 
237 		ooff = _dl_find_symbol("atexit", _dl_objects, &sym, 0, 0);
238 		if (sym == NULL) {
239 			_dl_printf("cannot find atexit, destructors will not be run!\n");
240 		} else {
241 			(*(void (*)(Elf_Addr))(sym->st_value + ooff))((Elf_Addr)_dl_dtors);
242 		}
243 	}
244 
245 
246 	/*
247 	 * Finally make something to help gdb when poking around in the code.
248 	 */
249 #if defined(__powerpc__) || defined(__alpha__)
250 	debug_map = (struct r_debug *)_dl_malloc(sizeof(*debug_map));
251 	debug_map->r_version = 1;
252 	debug_map->r_map = (struct link_map *)_dl_objects;
253 	debug_map->r_brk = (Elf_Addr)_dl_debug_state;
254 	debug_map->r_state = RT_CONSISTENT;
255 	debug_map->r_ldbase = loff;
256 	_dl_debug_map = debug_map;
257 
258 	/* Picks up the first object, the executable itself */
259 	dynobj = _dl_objects;
260 
261 	for (dynp = dynobj->load_dyn; dynp->d_tag; dynp++) {
262 		if (dynp->d_tag == DT_DEBUG) {
263 			dynp->d_un.d_ptr = (Elf_Addr) debug_map;
264 			break;
265 		}
266 	}
267 	if (dynp->d_tag != DT_DEBUG) {
268 		_dl_printf("failed to mark DTDEBUG\n");
269 	}
270 #endif
271 
272 #ifdef __mips__
273 	map_link = (struct r_debug **)(exe_obj->Dyn.info[DT_MIPS_RLD_MAP - DT_LOPROC + DT_NUM]);
274 	if (map_link) {
275 		debug_map = (struct r_debug *)_dl_malloc(sizeof(*debug_map));
276 		debug_map->r_version = 1;
277 		debug_map->r_map = (struct link_map *)_dl_objects;
278 		debug_map->r_brk = (Elf_Addr)_dl_debug_state;
279 		debug_map->r_state = RT_CONSISTENT;
280 		debug_map->r_ldbase = loff;
281 		_dl_debug_map = debug_map;
282 		*map_link = _dl_debug_map;
283 	}
284 #endif
285 
286 	_dl_debug_state();
287 
288 	if (_dl_debug || _dl_traceld) {
289 		void _dl_show_objects(); /* remove -Wall warning */
290 		_dl_show_objects();
291 		DL_DEB(("dynamic loading done.\n"));
292 	}
293 	_dl_unmaphints();
294 	if (_dl_traceld) {
295 		_dl_exit(0);
296 	}
297 
298 	/*
299 	 * Return the entry point.
300 	 */
301 	return(dl_data[AUX_entry]);
302 }
303 
304 
305 void
306 _dl_boot_bind(const long sp, const long loff,  int argc, const char **argv,
307 	const char **envp, Elf_Dyn *dynamicp, long *dl_data)
308 {
309 	AuxInfo		*auxstack;
310 	long		*stack;
311 	Elf_Dyn		*dynp;
312 	int		n;
313 
314 	struct elf_object  dynld;	/* Resolver data for the loader */
315 
316 	/*
317 	 * Scan argument and environment vectors. Find dynamic
318 	 * data vector put after them.
319 	 */
320 #ifdef _mips_
321 	stack = (long *)sp;
322 	argc = *stack++;
323 	argv = (const char **)stack;
324 	envp = &argv[argc + 1];
325 #endif /* _mips_ */
326 	stack = (long *)envp;
327 	while(*stack++ != NULL) {};
328 
329 	/*
330 	 * Dig out auxiliary data set up by exec call. Move all known
331 	 * tags to an indexed local table for easy access.
332 	 */
333 
334 	auxstack = (AuxInfo *)stack;
335 
336 	while (auxstack->au_id != AUX_null) {
337 		if (auxstack->au_id <= AUX_entry) {
338 			dl_data[auxstack->au_id] = auxstack->au_v;
339 		}
340 		auxstack++;
341 	}
342 
343 	/*
344 	 *  We need to do 'selfreloc' in case the code weren't
345 	 *  loaded at the address it was linked to.
346 	 *
347 	 *  Scan the DYNAMIC section for the loader.
348 	 *  Cache the data for easier access.
349 	 */
350 
351 #if defined(__powerpc__) || defined(__alpha__)
352 	dynp = dynamicp;
353 #else
354 	dynp = (Elf_Dyn *)((long)_DYNAMIC + loff);
355 #endif
356 	while (dynp != NULL && dynp->d_tag != DT_NULL) {
357 		if (dynp->d_tag < DT_LOPROC) {
358 			dynld.Dyn.info[dynp->d_tag] = dynp->d_un.d_val;
359 		} else if (dynp->d_tag >= DT_LOPROC && dynp->d_tag < DT_LOPROC + DT_NUM) {
360 			dynld.Dyn.info[dynp->d_tag + DT_NUM - DT_LOPROC] = dynp->d_un.d_val;
361 		}
362 		if (dynp->d_tag == DT_TEXTREL)
363 			dynld.dyn.textrel = 1;
364 		dynp++;
365 	}
366 
367 	/*
368 	 *  Do the 'bootstrap relocation'. This is really only needed if
369 	 *  the code was loaded at another location than it was linked to.
370 	 *  We don't do undefined symbols resolving (to difficult..)
371 	 */
372 
373 	/* "relocate" dyn.X values if they represent addresses */
374 	{
375 		int i, val;
376 		/* must be code, not pic data */
377 		int table[20];
378 		i = 0;
379 		table[i++] = DT_PLTGOT;
380 		table[i++] = DT_HASH;
381 		table[i++] = DT_STRTAB;
382 		table[i++] = DT_SYMTAB;
383 		table[i++] = DT_RELA;
384 		table[i++] = DT_INIT;
385 		table[i++] = DT_FINI;
386 		table[i++] = DT_REL;
387 		table[i++] = DT_JMPREL;
388 		/* other processors insert their extras here */
389 		table[i++] = DT_NULL;
390 		for (i = 0; table[i] != DT_NULL; i++) {
391 			val = table[i];
392 			if (val > DT_HIPROC) /* ??? */
393 				continue;
394 			if (val > DT_LOPROC)
395 				val -= DT_LOPROC + DT_NUM;
396 			if (dynld.Dyn.info[val] != 0)
397 				dynld.Dyn.info[val] += loff;
398 		}
399 
400 	}
401 
402 	{
403 		int	  i;
404 		u_int32_t rs;
405 		Elf_Rel  *rp;
406 
407 		rp = (Elf_Rel *)(dynld.Dyn.info[DT_REL]);
408 		rs = dynld.dyn.relsz;
409 
410 		for (i = 0; i < rs; i += sizeof (Elf_Rel)) {
411 			Elf_Addr *ra;
412 			const Elf_Sym  *sp;
413 
414 			sp = dynld.dyn.symtab;
415 			sp += ELF_R_SYM(rp->r_info);
416 
417 			if (ELF_R_SYM(rp->r_info) && sp->st_value == 0) {
418 #if 0
419 /* cannot printf in this function */
420 				_dl_wrstderr("Dynamic loader failure: self bootstrapping impossible.\n");
421 				_dl_wrstderr("Undefined symbol: ");
422 				_dl_wrstderr((char *)dynld.dyn.strtab
423 					+ sp->st_name);
424 #endif
425 				_dl_exit(5);
426 			}
427 
428 			ra = (Elf_Addr *)(rp->r_offset + loff);
429 			/*
430 			RELOC_REL(rp, sp, ra, loff);
431 			*/
432 			rp++;
433 		}
434 
435 	}
436 	for (n = 0; n < 2; n++) {
437 		int	  i;
438 		unsigned long rs;
439 		Elf_RelA  *rp;
440 
441 		switch (n) {
442 		case 0:
443 			rp = (Elf_RelA *)(dynld.Dyn.info[DT_JMPREL]);
444 			rs = dynld.dyn.pltrelsz;
445 			break;
446 		case 1:
447 			rp = (Elf_RelA *)(dynld.Dyn.info[DT_RELA]);
448 			rs = dynld.dyn.relasz;
449 			break;
450 		default:
451 			rp = NULL;
452 			rs = 0;
453 		}
454 		for (i = 0; i < rs; i += sizeof (Elf_RelA)) {
455 			Elf_Addr *ra;
456 			const Elf_Sym  *sp;
457 
458 			sp = dynld.dyn.symtab;
459 			sp += ELF_R_SYM(rp->r_info);
460 			if (ELF_R_SYM(rp->r_info) && sp->st_value == 0) {
461 #if 0
462 				_dl_wrstderr("Dynamic loader failure: self bootstrapping impossible.\n");
463 				_dl_wrstderr("Undefined symbol: ");
464 				_dl_wrstderr((char *)dynld.dyn.strtab
465 					+ sp->st_name);
466 #endif
467 				_dl_exit(6);
468 			}
469 
470 			ra = (Elf_Addr *)(rp->r_offset + loff);
471 
472 			RELOC_RELA(rp, sp, ra, loff);
473 
474 			rp++;
475 		}
476 	}
477 	/*
478 	 * we have been fully relocated here, so most things no longer
479 	 * need the loff adjustment
480 	 */
481 	return;
482 }
483 
484 
485 void
486 _dl_rtld(elf_object_t *object)
487 {
488 	if (object->next) {
489 		_dl_rtld(object->next);
490 	}
491 
492 	/*
493 	 *  Do relocation information first, then GOT.
494 	 */
495 	_dl_md_reloc(object, DT_REL, DT_RELSZ);
496 	_dl_md_reloc(object, DT_RELA, DT_RELASZ);
497 	if (_dl_bindnow || object->dyn.bind_now) {	/* XXX Perhaps more checking ? */
498 		_dl_md_reloc_got(object, 0);
499 	} else {
500 		_dl_md_reloc_got(object, 1);
501 	}
502 	object->status |= STAT_RELOC_DONE;
503 }
504 
505 void
506 _dl_call_init(elf_object_t *object)
507 {
508 	Elf_Addr ooff;
509 	const Elf_Sym  *sym;
510 	static void (*_dl_atexit)(Elf_Addr) = NULL;
511 
512 	if (object->next) {
513 		_dl_call_init(object->next);
514 	}
515 
516 	if (object->status & STAT_INIT_DONE) {
517 		return;
518 	}
519 
520 #ifndef __mips__
521 	if(object->dyn.init) {
522 		(*object->dyn.init)();
523 	}
524 /*
525  * XXX We perform relocation of DTOR/CTOR. This is a ld bug problem
526  * XXX that should be fixed.
527  */
528 	sym = 0;
529 	ooff = _dl_find_symbol("__CTOR_LIST__", object, &sym, 1, 1);
530 	if (sym) {
531 		int i = *(int *)(sym->st_value + ooff);
532 		while(i--) {
533 			*(int *)(sym->st_value + ooff + 4 + 4 * i) += ooff;
534 		}
535 	}
536 	sym = 0;
537 	ooff = _dl_find_symbol("__DTOR_LIST__", object, &sym, 1, 1);
538 	if (sym) {
539 		int i = *(int *)(sym->st_value + ooff);
540 		while(i--) {
541 			*(int *)(sym->st_value + ooff + 4 + 4 * i) += ooff;
542 		}
543 	}
544 
545 /*
546  * XXX We should really call any code which resides in the .init segment
547  * XXX but at the moment this functionality is not provided by the toolchain.
548  * XXX Instead we rely on a symbol named '.init' and call it if it exists.
549  */
550 	sym = 0;
551 	ooff = _dl_find_symbol(".init", object, &sym, 1, 1);
552 	if (sym) {
553 		DL_DEB(("calling .init in '%s'\n",object->load_name));
554 		(*(void(*)(void))(sym->st_value + ooff))();
555 	}
556 #if 0 /*XXX*/
557 	if (object->dyn.init) {
558 		(*object->dyn.init)();
559 	}
560 #endif
561 #endif /* __mips__ */
562 	object->status |= STAT_INIT_DONE;
563 }
564 
565 static char *
566 _dl_getenv(const char *var, const char **env)
567 {
568 	const char *ep;
569 
570 	while ((ep = *env++)) {
571 		const char *vp = var;
572 
573 		while (*vp && *vp == *ep) {
574 			vp++;
575 			ep++;
576 		}
577 		if (*vp == '\0' && *ep++ == '=') {
578 			return((char *)ep);
579 		}
580 	}
581 
582 	return(0);
583 }
584 
585 
586 /*
587  *  The following malloc/free code is a very simplified implementation
588  *  of a malloc function. However, we do not need to be very complex here
589  *  because we only free memory when 'dlclose()' is called and we can
590  *  reuse at least the memory allocated for the object descriptor. We have
591  *  one dynamic string allocated, the library name and it is likely that
592  *  we can reuse that one to without a lot of complex colapsing code.
593  */
594 
595 void *
596 _dl_malloc(int size)
597 {
598 	long *p;
599 	long *t, *n;
600 
601 	size = (size + 8 + DL_MALLOC_ALIGN - 1) & ~(DL_MALLOC_ALIGN - 1);
602 
603 	if ((t = _dl_malloc_free) != 0) {	/* Try free list first */
604 		n = (long *)&_dl_malloc_free;
605 		while (t && t[-1] < size) {
606 			n = t;
607 			t = (long *)*t;
608 		}
609 		if (t) {
610 			*n = *t;
611 			_dl_memset(t, 0, t[-1] - 4);
612 			return((void *)t);
613 		}
614 	}
615 	if ((_dl_malloc_pool == 0) ||
616 	    (_dl_malloc_pool + size > _dl_malloc_base + 4096)) {
617 		_dl_malloc_pool = (void *)_dl_mmap((void *)0, 4096,
618 						PROT_READ|PROT_WRITE,
619 						MAP_ANON|MAP_PRIVATE, -1, 0);
620 		if (_dl_malloc_pool == 0 || _dl_malloc_pool == MAP_FAILED ) {
621 			_dl_printf("Dynamic loader failure: malloc.\n");
622 			_dl_exit(7);
623 		}
624 		_dl_malloc_base = _dl_malloc_pool;
625 	}
626 	p = _dl_malloc_pool;
627 	_dl_malloc_pool += size;
628 	_dl_memset(p, 0, size);
629 	*p = size;
630 	return((void *)(p + 1));
631 }
632 
633 void
634 _dl_free(void *p)
635 {
636 	long *t = (long *)p;
637 
638 	*t = (long)_dl_malloc_free;
639 	_dl_malloc_free = p;
640 }
641