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