Annotation of src/libexec/ld.elf_so/rtld.c, Revision 1.31
1.31 ! erh 1: /* $NetBSD: rtld.c,v 1.30 2000/04/15 05:27:49 christos Exp $ */
1.1 cgd 2:
3: /*
4: * Copyright 1996 John D. Polstra.
5: * Copyright 1996 Matt Thomas <matt@3am-software.com>
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by John Polstra.
19: * 4. The name of the author may not be used to endorse or promote products
20: * derived from this software without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32: */
33:
34: /*
35: * Dynamic linker for ELF.
36: *
37: * John Polstra <jdp@polstra.com>.
38: */
39:
40: #include <err.h>
41: #include <errno.h>
42: #include <fcntl.h>
43: #include <stdarg.h>
44: #include <stdio.h>
45: #include <stdlib.h>
46: #include <string.h>
47: #include <unistd.h>
1.3 cgd 48: #include <sys/param.h>
1.1 cgd 49: #include <sys/mman.h>
50: #include <dirent.h>
51:
52: #include <ctype.h>
53:
1.2 cgd 54: #include <dlfcn.h>
1.1 cgd 55: #include "debug.h"
56: #include "rtld.h"
1.3 cgd 57:
1.20 kleink 58: #if !defined(lint)
1.3 cgd 59: #include "sysident.h"
1.20 kleink 60: #endif
1.1 cgd 61:
1.25 mycroft 62: #define END_SYM "_end"
63:
1.1 cgd 64: /*
65: * Debugging support.
66: */
67:
1.15 christos 68: typedef void (*funcptr) __P((void));
1.1 cgd 69:
70: /*
71: * Function declarations.
72: */
1.15 christos 73: static void _rtld_init __P((caddr_t));
74: static void _rtld_exit __P((void));
75:
76: Elf_Addr _rtld __P((Elf_Word *));
77:
1.1 cgd 78:
79: /*
80: * Data declarations.
81: */
1.15 christos 82: static char *error_message; /* Message for dlopen(), or NULL */
1.1 cgd 83:
1.15 christos 84: struct r_debug _rtld_debug; /* for GDB; */
85: bool _rtld_trust; /* False for setuid and setgid programs */
86: Obj_Entry *_rtld_objlist; /* Head of linked list of shared objects */
87: Obj_Entry **_rtld_objtail; /* Link field of last object in list */
88: Obj_Entry *_rtld_objmain; /* The main program shared object */
89: Obj_Entry _rtld_objself; /* The dynamic linker shared object */
90: char _rtld_path[] = _PATH_RTLD;
1.27 thorpej 91: unsigned long _rtld_curmark; /* Current mark value */
1.25 mycroft 92: Elf_Sym _rtld_sym_zero; /* For resolving undefined weak refs. */
1.18 ws 93: #ifdef VARPSZ
94: int _rtld_pagesz; /* Page size, as provided by kernel */
95: #endif
1.1 cgd 96:
1.25 mycroft 97: Objlist _rtld_list_global = /* Objects dlopened with RTLD_GLOBAL */
98: SIMPLEQ_HEAD_INITIALIZER(_rtld_list_global);
99: Objlist _rtld_list_main = /* Objects loaded at program startup */
100: SIMPLEQ_HEAD_INITIALIZER(_rtld_list_main);
101:
1.22 kleink 102: Search_Path *_rtld_default_paths;
1.15 christos 103: Search_Path *_rtld_paths;
1.28 christos 104:
105: Library_Xform *_rtld_xforms;
106:
1.1 cgd 107: /*
108: * Global declarations normally provided by crt0.
109: */
1.15 christos 110: char *__progname;
111: char **environ;
1.1 cgd 112:
1.9 tv 113: #ifdef OLD_GOT
114: extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
115: #else
116: extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
1.15 christos 117: extern Elf_Dyn _DYNAMIC;
1.1 cgd 118: #endif
1.8 tv 119:
1.15 christos 120: static void _rtld_call_fini_functions __P((Obj_Entry *));
121: static void _rtld_call_init_functions __P((Obj_Entry *));
122: static Obj_Entry *_rtld_dlcheck __P((void *));
1.25 mycroft 123: static void _rtld_init_dag __P((Obj_Entry *));
124: static void _rtld_init_dag1 __P((Obj_Entry *, Obj_Entry *));
125: static void _rtld_objlist_add __P((Objlist *, Obj_Entry *));
126: static Objlist_Entry *_rtld_objlist_find __P((Objlist *, const Obj_Entry *));
127: static void _rtld_objlist_remove __P((Objlist *, Obj_Entry *));
128: static void _rtld_unload_object __P((Obj_Entry *, bool));
129: static void _rtld_unref_dag __P((Obj_Entry *));
130: static Obj_Entry *_rtld_obj_from_addr __P((const void *));
1.15 christos 131:
1.1 cgd 132: static void
1.15 christos 133: _rtld_call_fini_functions(first)
134: Obj_Entry *first;
1.1 cgd 135: {
1.14 pk 136: Obj_Entry *obj;
1.1 cgd 137:
1.15 christos 138: for (obj = first; obj != NULL; obj = obj->next)
1.14 pk 139: if (obj->fini != NULL)
140: (*obj->fini)();
1.1 cgd 141: }
142:
143: static void
1.15 christos 144: _rtld_call_init_functions(first)
145: Obj_Entry *first;
1.1 cgd 146: {
1.14 pk 147: if (first != NULL) {
148: _rtld_call_init_functions(first->next);
149: if (first->init != NULL)
150: (*first->init)();
151: }
1.1 cgd 152: }
1.14 pk 153:
1.1 cgd 154: /*
155: * Initialize the dynamic linker. The argument is the address at which
156: * the dynamic linker has been mapped into memory. The primary task of
157: * this function is to relocate the dynamic linker.
158: */
159: static void
1.15 christos 160: _rtld_init(mapbase)
161: caddr_t mapbase;
1.1 cgd 162: {
1.15 christos 163: Obj_Entry objself;/* The dynamic linker shared object */
1.13 christos 164: #ifdef RTLD_RELOCATE_SELF
1.14 pk 165: int dodebug = false;
1.13 christos 166: #else
1.14 pk 167: int dodebug = true;
1.13 christos 168: #endif
1.1 cgd 169:
1.14 pk 170: memset(&objself, 0, sizeof objself);
171:
172: /* Conjure up an Obj_Entry structure for the dynamic linker. */
173: objself.path = NULL;
174: objself.rtld = true;
175: objself.mapbase = mapbase;
176:
1.13 christos 177: #if defined(__mips__)
1.14 pk 178: /*
179: * mips and ld.so currently linked at load address,
180: * so no relocation needed
181: */
182: objself.relocbase = 0;
1.6 mhitch 183: #else
1.14 pk 184: objself.relocbase = mapbase;
1.6 mhitch 185: #endif
1.14 pk 186:
187: objself.pltgot = NULL;
188:
1.1 cgd 189: #ifdef OLD_GOT
1.15 christos 190: objself.dynamic = (Elf_Dyn *) _GLOBAL_OFFSET_TABLE_[0];
1.1 cgd 191: #else
1.15 christos 192: objself.dynamic = (Elf_Dyn *) & _DYNAMIC;
1.1 cgd 193: #endif
194:
1.13 christos 195: #ifdef RTLD_RELOCATE_SELF
1.14 pk 196: /* We have not been relocated yet, so fix the dynamic address */
197: objself.dynamic = (Elf_Dyn *)
1.15 christos 198: ((u_long) mapbase + (char *) objself.dynamic);
199: #endif /* RTLD_RELOCATE_SELF */
1.13 christos 200:
1.14 pk 201: _rtld_digest_dynamic(&objself);
202:
1.1 cgd 203: #ifdef __alpha__
1.14 pk 204: /* XXX XXX XXX */
205: objself.pltgot = NULL;
1.1 cgd 206: #endif
1.14 pk 207: assert(objself.needed == NULL);
208:
1.12 christos 209: #if !defined(__mips__) && !defined(__i386__)
1.14 pk 210: /* no relocation for mips/i386 */
211: assert(!objself.textrel);
1.6 mhitch 212: #endif
1.1 cgd 213:
1.14 pk 214: _rtld_relocate_objects(&objself, true, dodebug);
1.13 christos 215:
1.14 pk 216: /*
217: * Now that we relocated ourselves, we can use globals.
218: */
219: _rtld_objself = objself;
1.13 christos 220:
1.14 pk 221: _rtld_objself.path = _rtld_path;
1.22 kleink 222: _rtld_add_paths(&_rtld_default_paths, RTLD_DEFAULT_LIBRARY_PATH, true);
1.13 christos 223:
1.14 pk 224: /*
225: * Set up the _rtld_objlist pointer, so that rtld symbols can be found.
226: */
227: _rtld_objlist = &_rtld_objself;
1.1 cgd 228:
1.14 pk 229: /* Make the object list empty again. */
230: _rtld_objlist = NULL;
231: _rtld_objtail = &_rtld_objlist;
1.1 cgd 232:
1.14 pk 233: _rtld_debug.r_brk = _rtld_debug_state;
234: _rtld_debug.r_state = RT_CONSISTENT;
1.1 cgd 235: }
1.14 pk 236:
1.1 cgd 237: /*
238: * Cleanup procedure. It will be called (by the atexit() mechanism) just
239: * before the process exits.
240: */
241: static void
1.15 christos 242: _rtld_exit()
1.1 cgd 243: {
1.15 christos 244: dbg(("rtld_exit()"));
1.1 cgd 245:
1.14 pk 246: _rtld_call_fini_functions(_rtld_objlist->next);
1.1 cgd 247: }
1.14 pk 248:
1.1 cgd 249: /*
250: * Main entry point for dynamic linking. The argument is the stack
251: * pointer. The stack is expected to be laid out as described in the
252: * SVR4 ABI specification, Intel 386 Processor Supplement. Specifically,
253: * the stack pointer points to a word containing ARGC. Following that
254: * in the stack is a null-terminated sequence of pointers to argument
255: * strings. Then comes a null-terminated sequence of pointers to
256: * environment strings. Finally, there is a sequence of "auxiliary
257: * vector" entries.
258: *
1.17 kleink 259: * This function returns the entry point for the main program, the dynamic
260: * linker's exit procedure in sp[0], and a pointer to the main object in
261: * sp[1].
1.1 cgd 262: */
263: Elf_Addr
1.15 christos 264: _rtld(sp)
265: Elf_Word *sp;
1.1 cgd 266: {
1.15 christos 267: const AuxInfo *pAUX_base, *pAUX_entry, *pAUX_execfd, *pAUX_phdr,
268: *pAUX_phent, *pAUX_phnum;
1.18 ws 269: #ifdef VARPSZ
270: const AuxInfo *pAUX_pagesz;
271: #endif
1.15 christos 272: char **env;
273: const AuxInfo *aux;
274: const AuxInfo *auxp;
275: Elf_Word *const osp = sp;
276: bool bind_now = 0;
277: const char *ld_bind_now;
278: const char **argv;
1.25 mycroft 279: Obj_Entry *obj;
1.31 ! erh 280: const char **real___progname;
! 281: char ***real_environ;
1.13 christos 282: #if defined(RTLD_DEBUG) && !defined(RTLD_RELOCATE_SELF)
1.15 christos 283: int i = 0;
1.12 christos 284: #endif
1.1 cgd 285:
1.15 christos 286: /*
287: * On entry, the dynamic linker itself has not been relocated yet.
288: * Be very careful not to reference any global data until after
289: * _rtld_init has returned. It is OK to reference file-scope statics
290: * and string constants, and to call static and global functions.
291: */
292: /* Find the auxiliary vector on the stack. */
293: /* first Elf_Word reserved to address of exit routine */
1.13 christos 294: #if defined(RTLD_DEBUG) && !defined(RTLD_RELOCATE_SELF)
1.16 christos 295: dbg(("sp = %p, argc = %ld, argv = %p <%s>\n", sp, (long)sp[2],
1.15 christos 296: &sp[3], (char *) sp[3]));
297: dbg(("got is at %p, dynamic is at %p\n",
298: _GLOBAL_OFFSET_TABLE_, &_DYNAMIC));
299: debug = 1;
300: dbg(("_ctype_ is %p\n", _ctype_));
1.1 cgd 301: #endif
302:
1.15 christos 303: sp += 2; /* skip over return argument space */
304: argv = (const char **) &sp[1];
305: sp += sp[0] + 2; /* Skip over argc, arguments, and NULL
306: * terminator */
307: env = (char **) sp;
308: while (*sp++ != 0) { /* Skip over environment, and NULL terminator */
1.13 christos 309: #if defined(RTLD_DEBUG) && !defined(RTLD_RELOCATE_SELF)
1.15 christos 310: dbg(("env[%d] = %p %s\n", i++, (void *)sp[-1], (char *)sp[-1]));
1.1 cgd 311: #endif
1.15 christos 312: }
313: aux = (const AuxInfo *) sp;
1.1 cgd 314:
1.15 christos 315: /* Digest the auxiliary vector. */
316: pAUX_base = pAUX_entry = pAUX_execfd = NULL;
317: pAUX_phdr = pAUX_phent = pAUX_phnum = NULL;
1.18 ws 318: #ifdef VARPSZ
319: pAUX_pagesz = NULL;
320: #endif
1.24 kleink 321: for (auxp = aux; auxp->a_type != AT_NULL; ++auxp) {
322: switch (auxp->a_type) {
323: case AT_BASE:
1.15 christos 324: pAUX_base = auxp;
325: break;
1.24 kleink 326: case AT_ENTRY:
1.15 christos 327: pAUX_entry = auxp;
328: break;
1.24 kleink 329: case AT_EXECFD:
1.15 christos 330: pAUX_execfd = auxp;
331: break;
1.24 kleink 332: case AT_PHDR:
1.15 christos 333: pAUX_phdr = auxp;
334: break;
1.24 kleink 335: case AT_PHENT:
1.15 christos 336: pAUX_phent = auxp;
337: break;
1.24 kleink 338: case AT_PHNUM:
1.15 christos 339: pAUX_phnum = auxp;
340: break;
1.18 ws 341: #ifdef VARPSZ
1.24 kleink 342: case AT_PAGESZ:
1.18 ws 343: pAUX_pagesz = auxp;
344: break;
345: #endif
1.15 christos 346: }
347: }
348:
349: /* Initialize and relocate ourselves. */
350: assert(pAUX_base != NULL);
1.24 kleink 351: _rtld_init((caddr_t) pAUX_base->a_v);
1.18 ws 352:
353: #ifdef VARPSZ
354: assert(pAUX_pagesz != NULL);
1.24 kleink 355: _rtld_pagesz = (int)pAUX_pagesz->a_v;
1.18 ws 356: #endif
1.1 cgd 357:
358: #ifdef RTLD_DEBUG
1.15 christos 359: dbg(("_ctype_ is %p\n", _ctype_));
1.1 cgd 360: #endif
361:
1.15 christos 362: __progname = _rtld_objself.path;
363: environ = env;
1.1 cgd 364:
1.15 christos 365: _rtld_trust = geteuid() == getuid() && getegid() == getgid();
1.1 cgd 366:
1.15 christos 367: ld_bind_now = getenv("LD_BIND_NOW");
368: if (ld_bind_now != NULL && *ld_bind_now != '\0')
369: bind_now = true;
370: if (_rtld_trust) {
1.6 mhitch 371: #ifdef DEBUG
1.15 christos 372: const char *ld_debug = getenv("LD_DEBUG");
373: if (ld_debug != NULL && *ld_debug != '\0')
374: debug = 1;
375: #endif
376: _rtld_add_paths(&_rtld_paths, getenv("LD_LIBRARY_PATH"), true);
377: }
1.28 christos 378: _rtld_process_hints(&_rtld_paths, &_rtld_xforms, _PATH_LD_HINTS, true);
1.15 christos 379: dbg(("%s is initialized, base address = %p", __progname,
1.24 kleink 380: (void *) pAUX_base->a_v));
1.15 christos 381:
382: /*
383: * Load the main program, or process its program header if it is
384: * already loaded.
385: */
386: if (pAUX_execfd != NULL) { /* Load the main program. */
1.24 kleink 387: int fd = pAUX_execfd->a_v;
1.15 christos 388: dbg(("loading main program"));
1.25 mycroft 389: _rtld_objmain = _rtld_map_object(argv[0], fd, NULL);
1.15 christos 390: close(fd);
391: if (_rtld_objmain == NULL)
392: _rtld_die();
393: } else { /* Main program already loaded. */
394: const Elf_Phdr *phdr;
395: int phnum;
396: caddr_t entry;
397:
398: dbg(("processing main program's program header"));
399: assert(pAUX_phdr != NULL);
1.24 kleink 400: phdr = (const Elf_Phdr *) pAUX_phdr->a_v;
1.15 christos 401: assert(pAUX_phnum != NULL);
1.24 kleink 402: phnum = pAUX_phnum->a_v;
1.15 christos 403: assert(pAUX_phent != NULL);
1.24 kleink 404: assert(pAUX_phent->a_v == sizeof(Elf_Phdr));
1.15 christos 405: assert(pAUX_entry != NULL);
1.24 kleink 406: entry = (caddr_t) pAUX_entry->a_v;
1.15 christos 407: _rtld_objmain = _rtld_digest_phdr(phdr, phnum, entry);
408: }
409:
410: _rtld_objmain->path = xstrdup("main program");
411: _rtld_objmain->mainprog = true;
1.25 mycroft 412:
413: /*
414: * Get the actual dynamic linker pathname from the executable if
415: * possible. (It should always be possible.) That ensures that
416: * gdb will find the right dynamic linker even if a non-standard
417: * one is being used.
418: */
419: if (_rtld_objmain->interp != NULL &&
420: strcmp(_rtld_objmain->interp, _rtld_objself.path) != 0) {
421: free(_rtld_objself.path);
422: _rtld_objself.path = xstrdup(_rtld_objmain->interp);
423: }
424:
1.15 christos 425: _rtld_digest_dynamic(_rtld_objmain);
426:
427: _rtld_linkmap_add(_rtld_objmain);
428: _rtld_linkmap_add(&_rtld_objself);
429:
430: /* Link the main program into the list of objects. */
431: *_rtld_objtail = _rtld_objmain;
432: _rtld_objtail = &_rtld_objmain->next;
433: ++_rtld_objmain->refcount;
1.19 kleink 434:
1.25 mycroft 435: /* Initialize a fake symbol for resolving undefined weak references. */
1.26 thorpej 436: _rtld_sym_zero.st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE);
1.25 mycroft 437: _rtld_sym_zero.st_shndx = SHN_ABS;
438:
1.19 kleink 439: /*
440: * Pre-load user-specified objects after the main program but before
441: * any shared object dependencies.
442: */
443: dbg(("preloading objects"));
444: if (_rtld_trust && _rtld_preload(getenv("LD_PRELOAD"), true) == -1)
445: _rtld_die();
1.15 christos 446:
447: dbg(("loading needed objects"));
1.28 christos 448: if (_rtld_load_needed_objects(_rtld_objmain, true) == -1)
1.15 christos 449: _rtld_die();
450:
1.25 mycroft 451: for (obj = _rtld_objlist; obj != NULL; obj = obj->next)
452: _rtld_objlist_add(&_rtld_list_main, obj);
453:
1.15 christos 454: dbg(("relocating objects"));
455: if (_rtld_relocate_objects(_rtld_objmain, bind_now, true) == -1)
456: _rtld_die();
457:
458: dbg(("doing copy relocations"));
459: if (_rtld_do_copy_relocations(_rtld_objmain, true) == -1)
460: _rtld_die();
461:
1.31 ! erh 462: /*
! 463: * Set the __progname and environ before calling
! 464: * anything that might use them.
! 465: */
! 466: real___progname = _rtld_objmain_sym("__progname");
! 467: if (real___progname) {
! 468: if ((*real___progname = strrchr(argv[0], '/')) == NULL)
! 469: (*real___progname) = argv[0];
! 470: else
! 471: (*real___progname)++;
! 472: }
! 473: real_environ = _rtld_objmain_sym("environ");
! 474: if (real_environ)
! 475: *real_environ = environ;
! 476:
1.15 christos 477: dbg(("calling _init functions"));
478: _rtld_call_init_functions(_rtld_objmain->next);
479:
480: dbg(("control at program entry point = %p, obj = %p, exit = %p",
481: _rtld_objmain->entry, _rtld_objmain, _rtld_exit));
482:
483: /*
484: * Return with the entry point and the exit procedure in at the top
485: * of stack.
486: */
487:
488: _rtld_debug_state(); /* say hello to gdb! */
489:
490: ((void **) osp)[0] = _rtld_exit;
491: ((void **) osp)[1] = _rtld_objmain;
492: return (Elf_Addr) _rtld_objmain->entry;
1.1 cgd 493: }
494:
495: void
1.15 christos 496: _rtld_die()
1.1 cgd 497: {
1.15 christos 498: const char *msg = _rtld_dlerror();
1.1 cgd 499:
1.15 christos 500: if (msg == NULL)
501: msg = "Fatal error";
502: xerrx(1, "%s\n", msg);
1.1 cgd 503: }
504:
505: static Obj_Entry *
1.15 christos 506: _rtld_dlcheck(handle)
507: void *handle;
1.1 cgd 508: {
1.15 christos 509: Obj_Entry *obj;
1.1 cgd 510:
1.15 christos 511: for (obj = _rtld_objlist; obj != NULL; obj = obj->next)
512: if (obj == (Obj_Entry *) handle)
513: break;
514:
515: if (obj == NULL || obj->dl_refcount == 0) {
516: xwarnx("Invalid shared object handle %p", handle);
517: return NULL;
518: }
519: return obj;
1.1 cgd 520: }
521:
522: static void
1.25 mycroft 523: _rtld_init_dag(root)
524: Obj_Entry *root;
525: {
1.27 thorpej 526: _rtld_curmark++;
1.25 mycroft 527: _rtld_init_dag1(root, root);
528: }
529:
530: static void
531: _rtld_init_dag1(root, obj)
532: Obj_Entry *root;
533: Obj_Entry *obj;
534: {
535: const Needed_Entry *needed;
536:
1.27 thorpej 537: if (obj->mark == _rtld_curmark)
1.25 mycroft 538: return;
1.27 thorpej 539: obj->mark = _rtld_curmark;
1.25 mycroft 540: _rtld_objlist_add(&obj->dldags, root);
541: _rtld_objlist_add(&root->dagmembers, obj);
542: for (needed = obj->needed; needed != NULL; needed = needed->next)
543: if (needed->obj != NULL)
544: _rtld_init_dag1(root, needed->obj);
545: }
546:
547: /*
548: * Note, this is called only for objects loaded by dlopen().
549: */
550: static void
551: _rtld_unload_object(root, do_fini_funcs)
552: Obj_Entry *root;
553: bool do_fini_funcs;
554: {
555: _rtld_unref_dag(root);
556: if (root->refcount == 0) { /* We are finished with some objects. */
557: Obj_Entry *obj;
558: Obj_Entry **linkp;
559: Objlist_Entry *elm;
560:
561: /* Finalize objects that are about to be unmapped. */
562: if (do_fini_funcs)
563: for (obj = _rtld_objlist->next; obj != NULL; obj = obj->next)
564: if (obj->refcount == 0 && obj->fini != NULL)
565: (*obj->fini)();
566:
567: /* Remove the DAG from all objects' DAG lists. */
568: for (elm = SIMPLEQ_FIRST(&root->dagmembers); elm; elm = SIMPLEQ_NEXT(elm, link))
569: _rtld_objlist_remove(&elm->obj->dldags, root);
570:
571: /* Remove the DAG from the RTLD_GLOBAL list. */
572: _rtld_objlist_remove(&_rtld_list_global, root);
573:
574: /* Unmap all objects that are no longer referenced. */
575: linkp = &_rtld_objlist->next;
576: while ((obj = *linkp) != NULL) {
577: if (obj->refcount == 0) {
578: #ifdef RTLD_DEBUG
579: dbg(("unloading \"%s\"", obj->path));
580: #endif
581: munmap(obj->mapbase, obj->mapsize);
582: _rtld_linkmap_delete(obj);
583: *linkp = obj->next;
584: _rtld_obj_free(obj);
585: } else
586: linkp = &obj->next;
587: }
588: _rtld_objtail = linkp;
589: }
590: }
591:
592: static void
593: _rtld_unref_dag(root)
1.15 christos 594: Obj_Entry *root;
1.1 cgd 595: {
1.15 christos 596: assert(root->refcount != 0);
597: --root->refcount;
598: if (root->refcount == 0) {
599: const Needed_Entry *needed;
600:
601: for (needed = root->needed; needed != NULL;
1.25 mycroft 602: needed = needed->next)
603: _rtld_unref_dag(needed->obj);
1.15 christos 604: }
1.1 cgd 605: }
606:
607: int
1.15 christos 608: _rtld_dlclose(handle)
609: void *handle;
1.1 cgd 610: {
1.15 christos 611: Obj_Entry *root = _rtld_dlcheck(handle);
1.1 cgd 612:
1.15 christos 613: if (root == NULL)
614: return -1;
1.1 cgd 615:
1.15 christos 616: _rtld_debug.r_state = RT_DELETE;
617: _rtld_debug_state();
618:
619: --root->dl_refcount;
1.29 kleink 620: _rtld_unload_object(root, true);
1.15 christos 621:
622: _rtld_debug.r_state = RT_CONSISTENT;
623: _rtld_debug_state();
1.1 cgd 624:
1.15 christos 625: return 0;
1.1 cgd 626: }
627:
628: char *
1.15 christos 629: _rtld_dlerror()
1.1 cgd 630: {
1.15 christos 631: char *msg = error_message;
632: error_message = NULL;
633: return msg;
1.1 cgd 634: }
635:
636: void *
1.15 christos 637: _rtld_dlopen(name, mode)
638: const char *name;
639: int mode;
640: {
641: Obj_Entry **old_obj_tail = _rtld_objtail;
642: Obj_Entry *obj = NULL;
643:
644: _rtld_debug.r_state = RT_ADD;
645: _rtld_debug_state();
646:
647: if (name == NULL) {
648: obj = _rtld_objmain;
1.25 mycroft 649: obj->refcount++;
1.15 christos 650: } else {
1.21 thorpej 651: char *path = _rtld_find_library(name, _rtld_objmain);
1.15 christos 652: if (path != NULL)
653: obj = _rtld_load_object(path, true);
1.1 cgd 654: }
655:
1.15 christos 656: if (obj != NULL) {
657: ++obj->dl_refcount;
1.25 mycroft 658: if (mode & RTLD_GLOBAL && _rtld_objlist_find(&_rtld_list_global, obj) == NULL)
659: _rtld_objlist_add(&_rtld_list_global, obj);
1.15 christos 660: if (*old_obj_tail != NULL) { /* We loaded something new. */
661: assert(*old_obj_tail == obj);
662:
1.28 christos 663: if (_rtld_load_needed_objects(obj, true) == -1 ||
664: (_rtld_init_dag(obj),
665: _rtld_relocate_objects(obj,
666: ((mode & 3) == RTLD_NOW), true)) == -1) {
1.25 mycroft 667: _rtld_unload_object(obj, false);
668: obj->dl_refcount--;
1.15 christos 669: obj = NULL;
1.25 mycroft 670: } else
1.15 christos 671: _rtld_call_init_functions(obj);
672: }
673: }
674: _rtld_debug.r_state = RT_CONSISTENT;
675: _rtld_debug_state();
1.1 cgd 676:
1.15 christos 677: return obj;
1.31 ! erh 678: }
! 679:
! 680: /*
! 681: * Find a symbol in the main program.
! 682: */
! 683: void *
! 684: _rtld_objmain_sym(name)
! 685: const char *name;
! 686: {
! 687: unsigned long hash;
! 688: const Elf_Sym *def;
! 689: const Obj_Entry *obj;
! 690:
! 691: hash = _rtld_elf_hash(name);
! 692: obj = _rtld_objmain;
! 693:
! 694: _rtld_curmark++;
! 695: def = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, true);
! 696:
! 697: if (def != NULL)
! 698: return obj->relocbase + def->st_value;
! 699: return(NULL);
1.1 cgd 700: }
701:
702: void *
1.15 christos 703: _rtld_dlsym(handle, name)
704: void *handle;
705: const char *name;
706: {
1.25 mycroft 707: const Obj_Entry *obj;
708: unsigned long hash;
709: const Elf_Sym *def;
1.15 christos 710: const Obj_Entry *defobj;
1.25 mycroft 711:
712: hash = _rtld_elf_hash(name);
713: def = NULL;
714: defobj = NULL;
715:
1.30 christos 716: if (handle == NULL
717: #if 0
718: || handle == RTLD_NEXT
719: #endif
720: ) {
721: void *retaddr;
722:
723: retaddr = __builtin_return_address(0); /* __GNUC__ only */
724: if ((obj = _rtld_obj_from_addr(retaddr)) == NULL) {
725: _rtld_error("Cannot determine caller's shared object");
726: return NULL;
727: }
728: if (handle == NULL) { /* Just the caller's shared object. */
729: def = _rtld_symlook_obj(name, hash, obj, true);
730: defobj = obj;
731: } else { /* All the shared objects after the caller's */
732: while ((obj = obj->next) != NULL) {
733: if ((def = _rtld_symlook_obj(name, hash, obj, true)) != NULL) {
734: defobj = obj;
735: break;
1.25 mycroft 736: }
737: }
1.30 christos 738: }
739: } else {
740: if ((obj = _rtld_dlcheck(handle)) == NULL)
741: return NULL;
742:
743: if (obj->mainprog) {
744: /* Search main program and all libraries loaded by it. */
745: _rtld_curmark++;
746: def = _rtld_symlook_list(name, hash, &_rtld_list_main, &defobj, true);
1.25 mycroft 747: } else {
1.30 christos 748: /*
749: * XXX - This isn't correct. The search should include the whole
750: * DAG rooted at the given object.
751: */
752: def = _rtld_symlook_obj(name, hash, obj, true);
753: defobj = obj;
1.25 mycroft 754: }
1.30 christos 755: }
756:
757: if (def != NULL)
758: return defobj->relocbase + def->st_value;
759:
760: _rtld_error("Undefined symbol \"%s\"", name);
1.25 mycroft 761: return NULL;
762: }
1.1 cgd 763:
1.25 mycroft 764: int
765: _rtld_dladdr(addr, info)
766: const void *addr;
767: Dl_info *info;
768: {
769: const Obj_Entry *obj;
770: const Elf_Sym *def;
771: void *symbol_addr;
772: unsigned long symoffset;
773:
774: obj = _rtld_obj_from_addr(addr);
775: if (obj == NULL) {
776: _rtld_error("No shared object contains address");
777: return 0;
778: }
779: info->dli_fname = obj->path;
780: info->dli_fbase = obj->mapbase;
781: info->dli_saddr = (void *)0;
782: info->dli_sname = NULL;
783:
1.15 christos 784: /*
1.25 mycroft 785: * Walk the symbol list looking for the symbol whose address is
786: * closest to the address sent in.
787: */
788: for (symoffset = 0; symoffset < obj->nchains; symoffset++) {
789: def = obj->symtab + symoffset;
790:
791: /*
792: * For skip the symbol if st_shndx is either SHN_UNDEF or
793: * SHN_COMMON.
794: */
795: if (def->st_shndx == SHN_UNDEF || def->st_shndx == SHN_COMMON)
796: continue;
797:
798: /*
799: * If the symbol is greater than the specified address, or if it
800: * is further away from addr than the current nearest symbol,
801: * then reject it.
802: */
803: symbol_addr = obj->relocbase + def->st_value;
804: if (symbol_addr > addr || symbol_addr < info->dli_saddr)
805: continue;
806:
807: /* Update our idea of the nearest symbol. */
808: info->dli_sname = obj->strtab + def->st_name;
809: info->dli_saddr = symbol_addr;
1.1 cgd 810:
1.25 mycroft 811: /* Exact match? */
812: if (info->dli_saddr == addr)
813: break;
814: }
815: return 1;
1.1 cgd 816: }
817:
818: /*
819: * Error reporting function. Use it like printf. If formats the message
820: * into a buffer, and sets things up so that the next call to dlerror()
821: * will return the message.
822: */
823: void
1.15 christos 824: #ifdef __STDC__
825: _rtld_error(const char *fmt,...)
826: #else
827: _rtld_error(va_alist)
828: va_dcl
829: #endif
1.1 cgd 830: {
1.15 christos 831: static char buf[512];
832: va_list ap;
833: #ifdef __STDC__
834: va_start(ap, fmt);
835: #else
836: const char *fmt;
1.1 cgd 837:
1.15 christos 838: va_start(ap);
839: fmt = va_arg(ap, const char *);
840: #endif
841: xvsnprintf(buf, sizeof buf, fmt, ap);
842: error_message = buf;
843: va_end(ap);
1.1 cgd 844: }
1.14 pk 845:
1.1 cgd 846: void
1.15 christos 847: _rtld_debug_state()
1.1 cgd 848: {
1.15 christos 849: /* do nothing */
1.1 cgd 850: }
851:
852: void
1.15 christos 853: _rtld_linkmap_add(obj)
854: Obj_Entry *obj;
1.1 cgd 855: {
1.15 christos 856: struct link_map *l = &obj->linkmap;
857: struct link_map *prev;
1.1 cgd 858:
1.15 christos 859: obj->linkmap.l_name = obj->path;
860: obj->linkmap.l_addr = obj->mapbase;
861: obj->linkmap.l_ld = obj->dynamic;
1.6 mhitch 862: #ifdef __mips__
1.15 christos 863: /* GDB needs load offset on MIPS to use the symbols */
864: obj->linkmap.l_offs = obj->relocbase;
1.6 mhitch 865: #endif
1.1 cgd 866:
1.15 christos 867: if (_rtld_debug.r_map == NULL) {
868: _rtld_debug.r_map = l;
869: return;
870: }
871: for (prev = _rtld_debug.r_map; prev->l_next != NULL; prev = prev->l_next);
872: l->l_prev = prev;
873: prev->l_next = l;
874: l->l_next = NULL;
1.1 cgd 875: }
876:
877: void
1.15 christos 878: _rtld_linkmap_delete(obj)
879: Obj_Entry *obj;
1.1 cgd 880: {
1.15 christos 881: struct link_map *l = &obj->linkmap;
1.1 cgd 882:
1.15 christos 883: if (l->l_prev == NULL) {
884: if ((_rtld_debug.r_map = l->l_next) != NULL)
885: l->l_next->l_prev = NULL;
886: return;
887: }
888: if ((l->l_prev->l_next = l->l_next) != NULL)
889: l->l_next->l_prev = l->l_prev;
1.25 mycroft 890: }
891:
892: static Obj_Entry *
893: _rtld_obj_from_addr(const void *addr)
894: {
895: unsigned long endhash;
896: Obj_Entry *obj;
897:
898: endhash = _rtld_elf_hash(END_SYM);
899: for (obj = _rtld_objlist; obj != NULL; obj = obj->next) {
900: const Elf_Sym *endsym;
901:
902: if (addr < (void *) obj->mapbase)
903: continue;
904: if ((endsym = _rtld_symlook_obj(END_SYM, endhash, obj, true)) == NULL)
905: continue; /* No "end" symbol?! */
906: if (addr < (void *) (obj->relocbase + endsym->st_value))
907: return obj;
908: }
909: return NULL;
910: }
911:
912: static void
913: _rtld_objlist_add(list, obj)
914: Objlist *list;
915: Obj_Entry *obj;
916: {
917: Objlist_Entry *elm;
918:
919: elm = NEW(Objlist_Entry);
920: elm->obj = obj;
921: SIMPLEQ_INSERT_TAIL(list, elm, link);
922: }
923:
924: static Objlist_Entry *
925: _rtld_objlist_find(Objlist *list, const Obj_Entry *obj)
926: {
927: Objlist_Entry *elm;
928:
929: for (elm = SIMPLEQ_FIRST(list); elm; elm = SIMPLEQ_NEXT(elm, link)) {
930: if (elm->obj == obj)
931: return elm;
932: }
933: return NULL;
934: }
935:
936: static void
937: _rtld_objlist_remove(list, obj)
938: Objlist *list;
939: Obj_Entry *obj;
940: {
941: Objlist_Entry *elm;
942:
943: if ((elm = _rtld_objlist_find(list, obj)) != NULL) {
944: if ((list)->sqh_first == (elm)) {
945: SIMPLEQ_REMOVE_HEAD(list, elm, link);
946: }
947: else {
948: struct Struct_Objlist_Entry *curelm = (list)->sqh_first;
949: while (curelm->link.sqe_next != (elm))
950: curelm = curelm->link.sqe_next;
951: if((curelm->link.sqe_next =
952: curelm->link.sqe_next->link.sqe_next) == NULL)
953: (list)->sqh_last = &(curelm)->link.sqe_next;
954: }
955: free(elm);
956: }
1.1 cgd 957: }
CVSweb <webmaster@jp.NetBSD.org>