Annotation of src/libexec/ld.elf_so/rtld.c, Revision 1.178
1.178 ! christos 1: /* $NetBSD: rtld.c,v 1.177 2015/04/06 09:34:15 yamt Exp $ */
1.1 cgd 2:
3: /*
4: * Copyright 1996 John D. Polstra.
5: * Copyright 1996 Matt Thomas <matt@3am-software.com>
1.87 mycroft 6: * Copyright 2002 Charles M. Hannum <root@ihack.net>
1.1 cgd 7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
19: * This product includes software developed by John Polstra.
20: * 4. The name of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33: */
34:
35: /*
36: * Dynamic linker for ELF.
37: *
38: * John Polstra <jdp@polstra.com>.
39: */
40:
1.107 skrll 41: #include <sys/cdefs.h>
42: #ifndef lint
1.178 ! christos 43: __RCSID("$NetBSD: rtld.c,v 1.177 2015/04/06 09:34:15 yamt Exp $");
1.107 skrll 44: #endif /* not lint */
45:
1.141 joerg 46: #include <sys/param.h>
47: #include <sys/atomic.h>
48: #include <sys/mman.h>
1.1 cgd 49: #include <err.h>
50: #include <errno.h>
51: #include <fcntl.h>
1.141 joerg 52: #include <lwp.h>
1.1 cgd 53: #include <stdarg.h>
54: #include <stdio.h>
55: #include <stdlib.h>
56: #include <string.h>
57: #include <unistd.h>
58: #include <dirent.h>
59:
60: #include <ctype.h>
61:
1.2 cgd 62: #include <dlfcn.h>
1.1 cgd 63: #include "debug.h"
64: #include "rtld.h"
1.3 cgd 65:
1.20 kleink 66: #if !defined(lint)
1.3 cgd 67: #include "sysident.h"
1.20 kleink 68: #endif
1.1 cgd 69:
70: /*
71: * Function declarations.
72: */
1.113 christos 73: static void _rtld_init(caddr_t, caddr_t, const char *);
1.98 skrll 74: static void _rtld_exit(void);
1.15 christos 75:
1.98 skrll 76: Elf_Addr _rtld(Elf_Addr *, Elf_Addr);
1.15 christos 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 */
1.131 skrll 90: u_int _rtld_objcount; /* Number of objects in _rtld_objlist */
91: u_int _rtld_objloads; /* Number of objects loaded in _rtld_objlist */
1.147 joerg 92: u_int _rtld_objgen; /* Generation count for _rtld_objlist */
1.120 matt 93: const char _rtld_path[] = _PATH_RTLD;
94:
95: /* Initialize a fake symbol for resolving undefined weak references. */
96: Elf_Sym _rtld_sym_zero = {
97: .st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
98: .st_shndx = SHN_ABS,
99: };
1.126 skrll 100: size_t _rtld_pagesz; /* Page size, as provided by kernel */
1.25 mycroft 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;
1.156 joerg 106: static void *auxinfo;
1.28 christos 107:
1.1 cgd 108: /*
109: * Global declarations normally provided by crt0.
110: */
1.15 christos 111: char *__progname;
112: char **environ;
1.1 cgd 113:
1.141 joerg 114: static volatile bool _rtld_mutex_may_recurse;
115:
1.108 uwe 116: #if defined(RTLD_DEBUG)
1.112 scw 117: #ifndef __sh__
1.9 tv 118: extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
1.108 uwe 119: #else /* 32-bit SuperH */
120: register Elf_Addr *_GLOBAL_OFFSET_TABLE_ asm("r12");
121: #endif
122: #endif /* RTLD_DEBUG */
1.15 christos 123: extern Elf_Dyn _DYNAMIC;
1.8 tv 124:
1.148 joerg 125: static void _rtld_call_fini_functions(sigset_t *, int);
126: static void _rtld_call_init_functions(sigset_t *);
1.117 ad 127: static void _rtld_initlist_visit(Objlist *, Obj_Entry *, int);
128: static void _rtld_initlist_tsort(Objlist *, int);
1.98 skrll 129: static Obj_Entry *_rtld_dlcheck(void *);
130: static void _rtld_init_dag(Obj_Entry *);
131: static void _rtld_init_dag1(Obj_Entry *, Obj_Entry *);
132: static void _rtld_objlist_remove(Objlist *, Obj_Entry *);
1.117 ad 133: static void _rtld_objlist_clear(Objlist *);
1.148 joerg 134: static void _rtld_unload_object(sigset_t *, Obj_Entry *, bool);
1.98 skrll 135: static void _rtld_unref_dag(Obj_Entry *);
136: static Obj_Entry *_rtld_obj_from_addr(const void *);
1.15 christos 137:
1.158 matt 138: static inline void
1.174 joerg 139: _rtld_call_initfini_function(const Obj_Entry *obj, Elf_Addr func, sigset_t *mask)
1.158 matt 140: {
141: _rtld_exclusive_exit(mask);
1.174 joerg 142: _rtld_call_function_void(obj, func);
1.158 matt 143: _rtld_exclusive_enter(mask);
144: }
145:
146: static void
147: _rtld_call_fini_function(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen)
148: {
1.174 joerg 149: if (obj->fini_arraysz == 0 && (obj->fini == 0 || obj->fini_called))
150: return;
151:
152: if (obj->fini != 0 && !obj->fini_called) {
1.158 matt 153: dbg (("calling fini function %s at %p%s", obj->path,
154: (void *)obj->fini,
155: obj->z_initfirst ? " (DF_1_INITFIRST)" : ""));
1.165 skrll 156: obj->fini_called = 1;
1.174 joerg 157: _rtld_call_initfini_function(obj, obj->fini, mask);
1.158 matt 158: }
159: #ifdef HAVE_INITFINI_ARRAY
160: /*
161: * Now process the fini_array if it exists. Simply go from
162: * start to end. We need to make restartable so just advance
163: * the array pointer and decrement the size each time through
164: * the loop.
165: */
166: while (obj->fini_arraysz > 0 && _rtld_objgen == cur_objgen) {
1.174 joerg 167: Elf_Addr fini = *obj->fini_array++;
1.158 matt 168: obj->fini_arraysz--;
169: dbg (("calling fini array function %s at %p%s", obj->path,
170: (void *)fini,
171: obj->z_initfirst ? " (DF_1_INITFIRST)" : ""));
1.174 joerg 172: _rtld_call_initfini_function(obj, fini, mask);
1.158 matt 173: }
174: #endif /* HAVE_INITFINI_ARRAY */
175: }
176:
1.1 cgd 177: static void
1.148 joerg 178: _rtld_call_fini_functions(sigset_t *mask, int force)
1.1 cgd 179: {
1.117 ad 180: Objlist_Entry *elm;
181: Objlist finilist;
1.147 joerg 182: u_int cur_objgen;
1.1 cgd 183:
1.117 ad 184: dbg(("_rtld_call_fini_functions(%d)", force));
185:
1.147 joerg 186: restart:
187: cur_objgen = ++_rtld_objgen;
1.117 ad 188: SIMPLEQ_INIT(&finilist);
189: _rtld_initlist_tsort(&finilist, 1);
190:
191: /* First pass: objects _not_ marked with DF_1_INITFIRST. */
192: SIMPLEQ_FOREACH(elm, &finilist, link) {
1.158 matt 193: Obj_Entry * const obj = elm->obj;
194: if (!obj->z_initfirst) {
195: if (obj->refcount > 0 && !force) {
196: continue;
197: }
198: /*
199: * XXX This can race against a concurrent dlclose().
200: * XXX In that case, the object could be unmapped before
201: * XXX the fini() call or the fini_array has completed.
202: */
203: _rtld_call_fini_function(obj, mask, cur_objgen);
204: if (_rtld_objgen != cur_objgen) {
205: dbg(("restarting fini iteration"));
206: _rtld_objlist_clear(&finilist);
207: goto restart;
1.117 ad 208: }
1.147 joerg 209: }
1.117 ad 210: }
211:
212: /* Second pass: objects marked with DF_1_INITFIRST. */
213: SIMPLEQ_FOREACH(elm, &finilist, link) {
1.158 matt 214: Obj_Entry * const obj = elm->obj;
1.117 ad 215: if (obj->refcount > 0 && !force) {
216: continue;
217: }
1.147 joerg 218: /* XXX See above for the race condition here */
1.158 matt 219: _rtld_call_fini_function(obj, mask, cur_objgen);
1.147 joerg 220: if (_rtld_objgen != cur_objgen) {
221: dbg(("restarting fini iteration"));
222: _rtld_objlist_clear(&finilist);
223: goto restart;
224: }
1.117 ad 225: }
226:
227: _rtld_objlist_clear(&finilist);
1.1 cgd 228: }
229:
230: static void
1.158 matt 231: _rtld_call_init_function(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen)
232: {
1.174 joerg 233: if (obj->init_arraysz == 0 && (obj->init_called || obj->init == 0))
1.158 matt 234: return;
1.174 joerg 235:
236: if (!obj->init_called && obj->init != 0) {
1.158 matt 237: dbg (("calling init function %s at %p%s",
238: obj->path, (void *)obj->init,
239: obj->z_initfirst ? " (DF_1_INITFIRST)" : ""));
240: obj->init_called = 1;
1.174 joerg 241: _rtld_call_initfini_function(obj, obj->init, mask);
1.158 matt 242: }
243:
244: #ifdef HAVE_INITFINI_ARRAY
245: /*
246: * Now process the init_array if it exists. Simply go from
247: * start to end. We need to make restartable so just advance
248: * the array pointer and decrement the size each time through
249: * the loop.
250: */
251: while (obj->init_arraysz > 0 && _rtld_objgen == cur_objgen) {
1.174 joerg 252: Elf_Addr init = *obj->init_array++;
1.158 matt 253: obj->init_arraysz--;
254: dbg (("calling init_array function %s at %p%s",
255: obj->path, (void *)init,
256: obj->z_initfirst ? " (DF_1_INITFIRST)" : ""));
1.174 joerg 257: _rtld_call_initfini_function(obj, init, mask);
1.158 matt 258: }
259: #endif /* HAVE_INITFINI_ARRAY */
260: }
261:
262: static void
1.148 joerg 263: _rtld_call_init_functions(sigset_t *mask)
1.1 cgd 264: {
1.117 ad 265: Objlist_Entry *elm;
266: Objlist initlist;
1.147 joerg 267: u_int cur_objgen;
1.94 simonb 268:
1.117 ad 269: dbg(("_rtld_call_init_functions()"));
1.147 joerg 270:
271: restart:
272: cur_objgen = ++_rtld_objgen;
1.117 ad 273: SIMPLEQ_INIT(&initlist);
274: _rtld_initlist_tsort(&initlist, 0);
275:
276: /* First pass: objects marked with DF_1_INITFIRST. */
277: SIMPLEQ_FOREACH(elm, &initlist, link) {
1.158 matt 278: Obj_Entry * const obj = elm->obj;
279: if (obj->z_initfirst) {
280: _rtld_call_init_function(obj, mask, cur_objgen);
281: if (_rtld_objgen != cur_objgen) {
282: dbg(("restarting init iteration"));
283: _rtld_objlist_clear(&initlist);
284: goto restart;
285: }
1.147 joerg 286: }
1.117 ad 287: }
288:
289: /* Second pass: all other objects. */
290: SIMPLEQ_FOREACH(elm, &initlist, link) {
1.158 matt 291: _rtld_call_init_function(elm->obj, mask, cur_objgen);
1.147 joerg 292: if (_rtld_objgen != cur_objgen) {
293: dbg(("restarting init iteration"));
294: _rtld_objlist_clear(&initlist);
295: goto restart;
296: }
1.14 pk 297: }
1.117 ad 298:
299: _rtld_objlist_clear(&initlist);
1.1 cgd 300: }
1.14 pk 301:
1.1 cgd 302: /*
303: * Initialize the dynamic linker. The argument is the address at which
304: * the dynamic linker has been mapped into memory. The primary task of
1.105 skrll 305: * this function is to create an Obj_Entry for the dynamic linker and
306: * to resolve the PLT relocation for platforms that need it (those that
307: * define __HAVE_FUNCTION_DESCRIPTORS
1.1 cgd 308: */
309: static void
1.114 christos 310: _rtld_init(caddr_t mapbase, caddr_t relocbase, const char *execname)
1.1 cgd 311: {
1.94 simonb 312:
1.14 pk 313: /* Conjure up an Obj_Entry structure for the dynamic linker. */
1.120 matt 314: _rtld_objself.path = __UNCONST(_rtld_path);
315: _rtld_objself.pathlen = sizeof(_rtld_path)-1;
1.80 mycroft 316: _rtld_objself.rtld = true;
317: _rtld_objself.mapbase = mapbase;
318: _rtld_objself.relocbase = relocbase;
319: _rtld_objself.dynamic = (Elf_Dyn *) &_DYNAMIC;
1.119 christos 320: _rtld_objself.strtab = "_rtld_sym_zero";
1.1 cgd 321:
1.120 matt 322: /*
1.128 skrll 323: * Set value to -relocbase so that
324: *
325: * _rtld_objself.relocbase + _rtld_sym_zero.st_value == 0
326: *
1.120 matt 327: * This allows unresolved references to weak symbols to be computed
1.128 skrll 328: * to a value of 0.
1.120 matt 329: */
330: _rtld_sym_zero.st_value = -(uintptr_t)relocbase;
331:
1.113 christos 332: _rtld_digest_dynamic(_rtld_path, &_rtld_objself);
1.104 skrll 333: assert(!_rtld_objself.needed);
1.105 skrll 334: #if !defined(__hppa__)
1.103 skrll 335: assert(!_rtld_objself.pltrel && !_rtld_objself.pltrela);
1.105 skrll 336: #else
337: _rtld_relocate_plt_objects(&_rtld_objself);
338: #endif
339: #if !defined(__mips__) && !defined(__hppa__)
1.104 skrll 340: assert(!_rtld_objself.pltgot);
1.103 skrll 341: #endif
1.97 skrll 342: #if !defined(__arm__) && !defined(__mips__) && !defined(__sh__)
343: /* ARM, MIPS and SH{3,5} have a bogus DT_TEXTREL. */
1.103 skrll 344: assert(!_rtld_objself.textrel);
1.80 mycroft 345: #endif
1.13 christos 346:
1.114 christos 347: _rtld_add_paths(execname, &_rtld_default_paths,
348: RTLD_DEFAULT_LIBRARY_PATH);
1.13 christos 349:
1.123 mrg 350: #ifdef RTLD_ARCH_SUBDIR
351: _rtld_add_paths(execname, &_rtld_default_paths,
352: RTLD_DEFAULT_LIBRARY_PATH "/" RTLD_ARCH_SUBDIR);
353: #endif
354:
1.169 skrll 355: /* Make the object list empty. */
1.14 pk 356: _rtld_objlist = NULL;
357: _rtld_objtail = &_rtld_objlist;
1.129 roy 358: _rtld_objcount = 0;
1.1 cgd 359:
1.14 pk 360: _rtld_debug.r_brk = _rtld_debug_state;
361: _rtld_debug.r_state = RT_CONSISTENT;
1.1 cgd 362: }
1.14 pk 363:
1.1 cgd 364: /*
365: * Cleanup procedure. It will be called (by the atexit() mechanism) just
366: * before the process exits.
367: */
368: static void
1.98 skrll 369: _rtld_exit(void)
1.1 cgd 370: {
1.148 joerg 371: sigset_t mask;
372:
1.15 christos 373: dbg(("rtld_exit()"));
1.1 cgd 374:
1.148 joerg 375: _rtld_exclusive_enter(&mask);
1.145 joerg 376:
1.148 joerg 377: _rtld_call_fini_functions(&mask, 1);
1.145 joerg 378:
1.148 joerg 379: _rtld_exclusive_exit(&mask);
1.1 cgd 380: }
1.14 pk 381:
1.156 joerg 382: __dso_public void *
383: _dlauxinfo(void)
384: {
385: return auxinfo;
386: }
387:
1.1 cgd 388: /*
389: * Main entry point for dynamic linking. The argument is the stack
390: * pointer. The stack is expected to be laid out as described in the
391: * SVR4 ABI specification, Intel 386 Processor Supplement. Specifically,
392: * the stack pointer points to a word containing ARGC. Following that
393: * in the stack is a null-terminated sequence of pointers to argument
394: * strings. Then comes a null-terminated sequence of pointers to
395: * environment strings. Finally, there is a sequence of "auxiliary
396: * vector" entries.
397: *
1.17 kleink 398: * This function returns the entry point for the main program, the dynamic
399: * linker's exit procedure in sp[0], and a pointer to the main object in
400: * sp[1].
1.1 cgd 401: */
402: Elf_Addr
1.98 skrll 403: _rtld(Elf_Addr *sp, Elf_Addr relocbase)
1.1 cgd 404: {
1.15 christos 405: const AuxInfo *pAUX_base, *pAUX_entry, *pAUX_execfd, *pAUX_phdr,
1.53 christos 406: *pAUX_phent, *pAUX_phnum, *pAUX_euid, *pAUX_egid,
407: *pAUX_ruid, *pAUX_rgid;
1.18 ws 408: const AuxInfo *pAUX_pagesz;
1.134 joerg 409: char **env, **oenvp;
1.15 christos 410: const AuxInfo *auxp;
1.139 joerg 411: Obj_Entry *obj;
1.39 mycroft 412: Elf_Addr *const osp = sp;
1.15 christos 413: bool bind_now = 0;
1.134 joerg 414: const char *ld_bind_now, *ld_preload, *ld_library_path;
1.15 christos 415: const char **argv;
1.114 christos 416: const char *execname;
1.40 mycroft 417: long argc;
1.31 erh 418: const char **real___progname;
1.34 christos 419: const Obj_Entry **real___mainprog_obj;
1.31 erh 420: char ***real_environ;
1.148 joerg 421: sigset_t mask;
1.134 joerg 422: #ifdef DEBUG
1.138 pooka 423: const char *ld_debug;
424: #endif
425: #ifdef RTLD_DEBUG
1.117 ad 426: int i = 0;
1.12 christos 427: #endif
1.1 cgd 428:
1.15 christos 429: /*
430: * On entry, the dynamic linker itself has not been relocated yet.
431: * Be very careful not to reference any global data until after
432: * _rtld_init has returned. It is OK to reference file-scope statics
433: * and string constants, and to call static and global functions.
434: */
435: /* Find the auxiliary vector on the stack. */
436: /* first Elf_Word reserved to address of exit routine */
1.60 mycroft 437: #if defined(RTLD_DEBUG)
1.75 mycroft 438: debug = 1;
1.88 fvdl 439: dbg(("sp = %p, argc = %ld, argv = %p <%s> relocbase %p", sp,
440: (long)sp[2], &sp[3], (char *) sp[3], (void *)relocbase));
1.164 skrll 441: #ifndef __x86_64__
1.75 mycroft 442: dbg(("got is at %p, dynamic is at %p", _GLOBAL_OFFSET_TABLE_,
443: &_DYNAMIC));
1.152 christos 444: #endif
1.162 matt 445: #endif
1.1 cgd 446:
1.15 christos 447: sp += 2; /* skip over return argument space */
448: argv = (const char **) &sp[1];
1.40 mycroft 449: argc = *(long *)sp;
1.39 mycroft 450: sp += 2 + argc; /* Skip over argc, arguments, and NULL
1.15 christos 451: * terminator */
452: env = (char **) sp;
453: while (*sp++ != 0) { /* Skip over environment, and NULL terminator */
1.60 mycroft 454: #if defined(RTLD_DEBUG)
1.71 junyoung 455: dbg(("env[%d] = %p %s", i++, (void *)sp[-1], (char *)sp[-1]));
1.1 cgd 456: #endif
1.15 christos 457: }
1.156 joerg 458: auxinfo = (AuxInfo *) sp;
1.1 cgd 459:
1.15 christos 460: pAUX_base = pAUX_entry = pAUX_execfd = NULL;
461: pAUX_phdr = pAUX_phent = pAUX_phnum = NULL;
1.53 christos 462: pAUX_euid = pAUX_ruid = pAUX_egid = pAUX_rgid = NULL;
1.18 ws 463: pAUX_pagesz = NULL;
1.44 pk 464:
1.114 christos 465: execname = NULL;
466:
1.69 mycroft 467: /* Digest the auxiliary vector. */
1.156 joerg 468: for (auxp = auxinfo; auxp->a_type != AT_NULL; ++auxp) {
1.24 kleink 469: switch (auxp->a_type) {
470: case AT_BASE:
1.15 christos 471: pAUX_base = auxp;
472: break;
1.24 kleink 473: case AT_ENTRY:
1.15 christos 474: pAUX_entry = auxp;
475: break;
1.24 kleink 476: case AT_EXECFD:
1.15 christos 477: pAUX_execfd = auxp;
478: break;
1.24 kleink 479: case AT_PHDR:
1.15 christos 480: pAUX_phdr = auxp;
481: break;
1.24 kleink 482: case AT_PHENT:
1.15 christos 483: pAUX_phent = auxp;
484: break;
1.24 kleink 485: case AT_PHNUM:
1.15 christos 486: pAUX_phnum = auxp;
487: break;
1.54 mycroft 488: #ifdef AT_EUID
1.53 christos 489: case AT_EUID:
490: pAUX_euid = auxp;
491: break;
492: case AT_RUID:
493: pAUX_ruid = auxp;
494: break;
495: case AT_EGID:
496: pAUX_egid = auxp;
497: break;
498: case AT_RGID:
499: pAUX_rgid = auxp;
500: break;
1.54 mycroft 501: #endif
1.114 christos 502: #ifdef AT_SUN_EXECNAME
503: case AT_SUN_EXECNAME:
504: execname = (const char *)(const void *)auxp->a_v;
505: break;
506: #endif
1.24 kleink 507: case AT_PAGESZ:
1.18 ws 508: pAUX_pagesz = auxp;
509: break;
1.15 christos 510: }
511: }
1.18 ws 512:
1.69 mycroft 513: /* Initialize and relocate ourselves. */
1.90 junyoung 514: if (pAUX_base == NULL) {
515: _rtld_error("Bad pAUX_base");
516: _rtld_die();
517: }
1.69 mycroft 518: assert(pAUX_pagesz != NULL);
1.24 kleink 519: _rtld_pagesz = (int)pAUX_pagesz->a_v;
1.114 christos 520: _rtld_init((caddr_t)pAUX_base->a_v, (caddr_t)relocbase, execname);
1.1 cgd 521:
1.15 christos 522: __progname = _rtld_objself.path;
523: environ = env;
1.1 cgd 524:
1.53 christos 525: _rtld_trust = ((pAUX_euid ? (uid_t)pAUX_euid->a_v : geteuid()) ==
526: (pAUX_ruid ? (uid_t)pAUX_ruid->a_v : getuid())) &&
527: ((pAUX_egid ? (gid_t)pAUX_egid->a_v : getegid()) ==
528: (pAUX_rgid ? (gid_t)pAUX_rgid->a_v : getgid()));
1.1 cgd 529:
1.134 joerg 530: #ifdef DEBUG
531: ld_debug = NULL;
532: #endif
533: ld_bind_now = NULL;
534: ld_library_path = NULL;
535: ld_preload = NULL;
536: /*
537: * Inline avoid using normal getenv/unsetenv here as the libc
538: * code is quite a bit more complicated.
539: */
540: for (oenvp = env; *env != NULL; ++env) {
541: static const char bind_var[] = "LD_BIND_NOW=";
542: static const char debug_var[] = "LD_DEBUG=";
543: static const char path_var[] = "LD_LIBRARY_PATH=";
544: static const char preload_var[] = "LD_PRELOAD=";
545: #define LEN(x) (sizeof(x) - 1)
546:
547: if ((*env)[0] != 'L' || (*env)[1] != 'D') {
548: /*
549: * Special case to skip most entries without
550: * the more expensive calls to strncmp.
551: */
552: *oenvp++ = *env;
553: } else if (strncmp(*env, debug_var, LEN(debug_var)) == 0) {
554: if (_rtld_trust) {
555: #ifdef DEBUG
556: ld_debug = *env + LEN(debug_var);
557: #endif
558: *oenvp++ = *env;
559: }
560: } else if (strncmp(*env, bind_var, LEN(bind_var)) == 0) {
1.173 joerg 561: if (_rtld_trust) {
562: ld_bind_now = *env + LEN(bind_var);
563: *oenvp++ = *env;
564: }
1.134 joerg 565: } else if (strncmp(*env, path_var, LEN(path_var)) == 0) {
566: if (_rtld_trust) {
567: ld_library_path = *env + LEN(path_var);
568: *oenvp++ = *env;
569: }
570: } else if (strncmp(*env, preload_var, LEN(preload_var)) == 0) {
571: if (_rtld_trust) {
572: ld_preload = *env + LEN(preload_var);
573: *oenvp++ = *env;
574: }
575: } else {
576: *oenvp++ = *env;
577: }
578: #undef LEN
579: }
580: *oenvp++ = NULL;
581:
1.15 christos 582: if (ld_bind_now != NULL && *ld_bind_now != '\0')
583: bind_now = true;
584: if (_rtld_trust) {
1.6 mhitch 585: #ifdef DEBUG
1.75 mycroft 586: #ifdef RTLD_DEBUG
587: debug = 0;
588: #endif
1.15 christos 589: if (ld_debug != NULL && *ld_debug != '\0')
590: debug = 1;
591: #endif
1.134 joerg 592: _rtld_add_paths(execname, &_rtld_paths, ld_library_path);
1.111 christos 593: } else {
1.115 christos 594: execname = NULL;
1.15 christos 595: }
1.114 christos 596: _rtld_process_hints(execname, &_rtld_paths, &_rtld_xforms,
1.113 christos 597: _PATH_LD_HINTS);
1.66 junyoung 598: dbg(("dynamic linker is initialized, mapbase=%p, relocbase=%p",
1.58 mycroft 599: _rtld_objself.mapbase, _rtld_objself.relocbase));
1.15 christos 600:
601: /*
602: * Load the main program, or process its program header if it is
603: * already loaded.
604: */
605: if (pAUX_execfd != NULL) { /* Load the main program. */
1.24 kleink 606: int fd = pAUX_execfd->a_v;
1.110 christos 607: const char *obj_name = argv[0] ? argv[0] : "main program";
1.15 christos 608: dbg(("loading main program"));
1.110 christos 609: _rtld_objmain = _rtld_map_object(obj_name, fd, NULL);
1.15 christos 610: close(fd);
611: if (_rtld_objmain == NULL)
612: _rtld_die();
613: } else { /* Main program already loaded. */
614: const Elf_Phdr *phdr;
615: int phnum;
616: caddr_t entry;
617:
618: dbg(("processing main program's program header"));
619: assert(pAUX_phdr != NULL);
1.24 kleink 620: phdr = (const Elf_Phdr *) pAUX_phdr->a_v;
1.15 christos 621: assert(pAUX_phnum != NULL);
1.24 kleink 622: phnum = pAUX_phnum->a_v;
1.15 christos 623: assert(pAUX_phent != NULL);
1.24 kleink 624: assert(pAUX_phent->a_v == sizeof(Elf_Phdr));
1.15 christos 625: assert(pAUX_entry != NULL);
1.24 kleink 626: entry = (caddr_t) pAUX_entry->a_v;
1.15 christos 627: _rtld_objmain = _rtld_digest_phdr(phdr, phnum, entry);
1.84 mycroft 628: _rtld_objmain->path = xstrdup(argv[0] ? argv[0] :
629: "main program");
1.89 junyoung 630: _rtld_objmain->pathlen = strlen(_rtld_objmain->path);
1.15 christos 631: }
632:
1.92 mycroft 633: _rtld_objmain->mainprog = true;
1.165 skrll 634:
1.25 mycroft 635: /*
636: * Get the actual dynamic linker pathname from the executable if
637: * possible. (It should always be possible.) That ensures that
638: * gdb will find the right dynamic linker even if a non-standard
639: * one is being used.
640: */
641: if (_rtld_objmain->interp != NULL &&
1.171 skrll 642: strcmp(_rtld_objmain->interp, _rtld_objself.path) != 0) {
1.25 mycroft 643: _rtld_objself.path = xstrdup(_rtld_objmain->interp);
1.171 skrll 644: _rtld_objself.pathlen = strlen(_rtld_objself.path);
645: }
1.66 junyoung 646: dbg(("actual dynamic linker is %s", _rtld_objself.path));
1.165 skrll 647:
1.114 christos 648: _rtld_digest_dynamic(execname, _rtld_objmain);
1.15 christos 649:
1.84 mycroft 650: /* Link the main program into the list of objects. */
651: *_rtld_objtail = _rtld_objmain;
652: _rtld_objtail = &_rtld_objmain->next;
1.131 skrll 653: _rtld_objcount++;
654: _rtld_objloads++;
1.84 mycroft 655:
1.15 christos 656: _rtld_linkmap_add(_rtld_objmain);
1.178 ! christos 657: _rtld_objself.path = xstrdup(_rtld_objself.path);
1.15 christos 658: _rtld_linkmap_add(&_rtld_objself);
659:
660: ++_rtld_objmain->refcount;
1.84 mycroft 661: _rtld_objmain->mainref = 1;
1.117 ad 662: _rtld_objlist_push_tail(&_rtld_list_main, _rtld_objmain);
1.19 kleink 663:
1.134 joerg 664: if (ld_preload) {
1.111 christos 665: /*
666: * Pre-load user-specified objects after the main program
667: * but before any shared object dependencies.
668: */
669: dbg(("preloading objects"));
1.134 joerg 670: if (_rtld_preload(ld_preload) == -1)
1.127 christos 671: _rtld_die();
1.134 joerg 672: }
1.15 christos 673:
674: dbg(("loading needed objects"));
1.137 skrll 675: if (_rtld_load_needed_objects(_rtld_objmain, _RTLD_MAIN) == -1)
1.15 christos 676: _rtld_die();
677:
1.151 nonaka 678: dbg(("checking for required versions"));
679: for (obj = _rtld_objlist; obj != NULL; obj = obj->next) {
680: if (_rtld_verify_object_versions(obj) == -1)
681: _rtld_die();
682: }
683:
1.139 joerg 684: #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
1.154 joerg 685: dbg(("initializing initial Thread Local Storage offsets"));
1.139 joerg 686: /*
687: * All initial objects get the TLS space from the static block.
688: */
689: for (obj = _rtld_objlist; obj != NULL; obj = obj->next)
690: _rtld_tls_offset_allocate(obj);
691: #endif
692:
1.15 christos 693: dbg(("relocating objects"));
1.81 mycroft 694: if (_rtld_relocate_objects(_rtld_objmain, bind_now) == -1)
1.15 christos 695: _rtld_die();
696:
697: dbg(("doing copy relocations"));
1.60 mycroft 698: if (_rtld_do_copy_relocations(_rtld_objmain) == -1)
1.15 christos 699: _rtld_die();
700:
1.154 joerg 701: #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
702: dbg(("initializing Thread Local Storage for main thread"));
703: /*
704: * Set up TLS area for the main thread.
705: * This has to be done after all relocations are processed,
706: * since .tdata may contain relocations.
707: */
708: _rtld_tls_initial_allocation();
709: #endif
710:
1.31 erh 711: /*
1.34 christos 712: * Set the __progname, environ and, __mainprog_obj before
713: * calling anything that might use them.
1.31 erh 714: */
715: real___progname = _rtld_objmain_sym("__progname");
716: if (real___progname) {
1.64 christos 717: if (argv[0] != NULL) {
718: if ((*real___progname = strrchr(argv[0], '/')) == NULL)
719: (*real___progname) = argv[0];
720: else
721: (*real___progname)++;
722: } else {
723: (*real___progname) = NULL;
724: }
1.31 erh 725: }
726: real_environ = _rtld_objmain_sym("environ");
727: if (real_environ)
728: *real_environ = environ;
1.99 skrll 729: /*
730: * Set __mainprog_obj for old binaries.
731: */
1.34 christos 732: real___mainprog_obj = _rtld_objmain_sym("__mainprog_obj");
733: if (real___mainprog_obj)
734: *real___mainprog_obj = _rtld_objmain;
1.31 erh 735:
1.148 joerg 736: _rtld_exclusive_enter(&mask);
1.141 joerg 737:
1.15 christos 738: dbg(("calling _init functions"));
1.148 joerg 739: _rtld_call_init_functions(&mask);
1.15 christos 740:
741: dbg(("control at program entry point = %p, obj = %p, exit = %p",
742: _rtld_objmain->entry, _rtld_objmain, _rtld_exit));
743:
1.148 joerg 744: _rtld_exclusive_exit(&mask);
1.141 joerg 745:
1.15 christos 746: /*
747: * Return with the entry point and the exit procedure in at the top
748: * of stack.
749: */
750:
751: _rtld_debug_state(); /* say hello to gdb! */
752:
753: ((void **) osp)[0] = _rtld_exit;
754: ((void **) osp)[1] = _rtld_objmain;
755: return (Elf_Addr) _rtld_objmain->entry;
1.1 cgd 756: }
757:
758: void
1.98 skrll 759: _rtld_die(void)
1.1 cgd 760: {
1.99 skrll 761: const char *msg = dlerror();
1.1 cgd 762:
1.15 christos 763: if (msg == NULL)
764: msg = "Fatal error";
1.52 soren 765: xerrx(1, "%s", msg);
1.1 cgd 766: }
767:
768: static Obj_Entry *
1.98 skrll 769: _rtld_dlcheck(void *handle)
1.1 cgd 770: {
1.15 christos 771: Obj_Entry *obj;
1.1 cgd 772:
1.15 christos 773: for (obj = _rtld_objlist; obj != NULL; obj = obj->next)
774: if (obj == (Obj_Entry *) handle)
775: break;
776:
777: if (obj == NULL || obj->dl_refcount == 0) {
1.159 riastrad 778: _rtld_error("Invalid shared object handle %p", handle);
1.15 christos 779: return NULL;
780: }
781: return obj;
1.1 cgd 782: }
783:
784: static void
1.117 ad 785: _rtld_initlist_visit(Objlist* list, Obj_Entry *obj, int rev)
786: {
787: Needed_Entry* elm;
788:
789: /* dbg(("_rtld_initlist_visit(%s)", obj->path)); */
790:
791: if (obj->init_done)
792: return;
793: obj->init_done = 1;
794:
795: for (elm = obj->needed; elm != NULL; elm = elm->next) {
796: if (elm->obj != NULL) {
797: _rtld_initlist_visit(list, elm->obj, rev);
798: }
799: }
800:
801: if (rev) {
802: _rtld_objlist_push_head(list, obj);
803: } else {
804: _rtld_objlist_push_tail(list, obj);
805: }
806: }
807:
808: static void
809: _rtld_initlist_tsort(Objlist* list, int rev)
810: {
811: dbg(("_rtld_initlist_tsort"));
812:
813: Obj_Entry* obj;
814:
815: for (obj = _rtld_objlist->next; obj; obj = obj->next) {
816: obj->init_done = 0;
817: }
818:
819: for (obj = _rtld_objlist->next; obj; obj = obj->next) {
820: _rtld_initlist_visit(list, obj, rev);
821: }
822: }
823:
824: static void
1.98 skrll 825: _rtld_init_dag(Obj_Entry *root)
1.25 mycroft 826: {
1.94 simonb 827:
1.25 mycroft 828: _rtld_init_dag1(root, root);
829: }
830:
831: static void
1.98 skrll 832: _rtld_init_dag1(Obj_Entry *root, Obj_Entry *obj)
1.25 mycroft 833: {
834: const Needed_Entry *needed;
835:
1.84 mycroft 836: if (!obj->mainref) {
837: if (_rtld_objlist_find(&obj->dldags, root))
838: return;
1.133 skrll 839: dbg(("add %p (%s) to %p (%s) DAG", obj, obj->path, root,
1.84 mycroft 840: root->path));
1.117 ad 841: _rtld_objlist_push_tail(&obj->dldags, root);
842: _rtld_objlist_push_tail(&root->dagmembers, obj);
1.84 mycroft 843: }
1.25 mycroft 844: for (needed = obj->needed; needed != NULL; needed = needed->next)
845: if (needed->obj != NULL)
846: _rtld_init_dag1(root, needed->obj);
847: }
848:
849: /*
850: * Note, this is called only for objects loaded by dlopen().
851: */
852: static void
1.148 joerg 853: _rtld_unload_object(sigset_t *mask, Obj_Entry *root, bool do_fini_funcs)
1.25 mycroft 854: {
1.94 simonb 855:
1.25 mycroft 856: _rtld_unref_dag(root);
857: if (root->refcount == 0) { /* We are finished with some objects. */
858: Obj_Entry *obj;
859: Obj_Entry **linkp;
860: Objlist_Entry *elm;
861:
862: /* Finalize objects that are about to be unmapped. */
863: if (do_fini_funcs)
1.148 joerg 864: _rtld_call_fini_functions(mask, 0);
1.25 mycroft 865:
866: /* Remove the DAG from all objects' DAG lists. */
1.50 lukem 867: SIMPLEQ_FOREACH(elm, &root->dagmembers, link)
1.25 mycroft 868: _rtld_objlist_remove(&elm->obj->dldags, root);
869:
870: /* Remove the DAG from the RTLD_GLOBAL list. */
1.84 mycroft 871: if (root->globalref) {
872: root->globalref = 0;
873: _rtld_objlist_remove(&_rtld_list_global, root);
874: }
1.25 mycroft 875:
876: /* Unmap all objects that are no longer referenced. */
877: linkp = &_rtld_objlist->next;
878: while ((obj = *linkp) != NULL) {
879: if (obj->refcount == 0) {
880: dbg(("unloading \"%s\"", obj->path));
1.118 ad 881: if (obj->ehdr != MAP_FAILED)
882: munmap(obj->ehdr, _rtld_pagesz);
1.25 mycroft 883: munmap(obj->mapbase, obj->mapsize);
1.45 christos 884: _rtld_objlist_remove(&_rtld_list_global, obj);
1.25 mycroft 885: _rtld_linkmap_delete(obj);
886: *linkp = obj->next;
1.129 roy 887: _rtld_objcount--;
1.25 mycroft 888: _rtld_obj_free(obj);
889: } else
890: linkp = &obj->next;
891: }
892: _rtld_objtail = linkp;
893: }
894: }
895:
1.137 skrll 896: void
897: _rtld_ref_dag(Obj_Entry *root)
898: {
899: const Needed_Entry *needed;
900:
901: assert(root);
902:
903: ++root->refcount;
904:
905: dbg(("incremented reference on \"%s\" (%d)", root->path,
906: root->refcount));
907: for (needed = root->needed; needed != NULL;
908: needed = needed->next) {
909: if (needed->obj != NULL)
910: _rtld_ref_dag(needed->obj);
911: }
912: }
913:
1.25 mycroft 914: static void
1.98 skrll 915: _rtld_unref_dag(Obj_Entry *root)
1.1 cgd 916: {
1.94 simonb 917:
1.33 jdolecek 918: assert(root);
1.15 christos 919: assert(root->refcount != 0);
1.137 skrll 920:
1.15 christos 921: --root->refcount;
1.137 skrll 922: dbg(("decremented reference on \"%s\" (%d)", root->path,
923: root->refcount));
924:
1.15 christos 925: if (root->refcount == 0) {
926: const Needed_Entry *needed;
927:
928: for (needed = root->needed; needed != NULL;
1.32 jdolecek 929: needed = needed->next) {
930: if (needed->obj != NULL)
931: _rtld_unref_dag(needed->obj);
932: }
1.15 christos 933: }
1.1 cgd 934: }
935:
1.106 thorpej 936: __strong_alias(__dlclose,dlclose)
1.1 cgd 937: int
1.99 skrll 938: dlclose(void *handle)
1.1 cgd 939: {
1.143 joerg 940: Obj_Entry *root;
1.148 joerg 941: sigset_t mask;
1.1 cgd 942:
1.144 joerg 943: dbg(("dlclose of %p", handle));
1.143 joerg 944:
1.148 joerg 945: _rtld_exclusive_enter(&mask);
1.143 joerg 946:
947: root = _rtld_dlcheck(handle);
948:
949: if (root == NULL) {
1.148 joerg 950: _rtld_exclusive_exit(&mask);
1.15 christos 951: return -1;
1.143 joerg 952: }
1.1 cgd 953:
1.15 christos 954: _rtld_debug.r_state = RT_DELETE;
955: _rtld_debug_state();
956:
957: --root->dl_refcount;
1.148 joerg 958: _rtld_unload_object(&mask, root, true);
1.15 christos 959:
960: _rtld_debug.r_state = RT_CONSISTENT;
961: _rtld_debug_state();
1.1 cgd 962:
1.148 joerg 963: _rtld_exclusive_exit(&mask);
1.143 joerg 964:
1.15 christos 965: return 0;
1.1 cgd 966: }
967:
1.106 thorpej 968: __strong_alias(__dlerror,dlerror)
1.1 cgd 969: char *
1.99 skrll 970: dlerror(void)
1.1 cgd 971: {
1.15 christos 972: char *msg = error_message;
1.94 simonb 973:
1.15 christos 974: error_message = NULL;
975: return msg;
1.1 cgd 976: }
977:
1.106 thorpej 978: __strong_alias(__dlopen,dlopen)
1.1 cgd 979: void *
1.99 skrll 980: dlopen(const char *name, int mode)
1.15 christos 981: {
982: Obj_Entry **old_obj_tail = _rtld_objtail;
983: Obj_Entry *obj = NULL;
1.137 skrll 984: int flags = _RTLD_DLOPEN;
985: bool nodelete;
986: bool now;
1.148 joerg 987: sigset_t mask;
1.151 nonaka 988: int result;
1.137 skrll 989:
1.144 joerg 990: dbg(("dlopen of %s %d", name, mode));
991:
1.148 joerg 992: _rtld_exclusive_enter(&mask);
1.141 joerg 993:
1.137 skrll 994: flags |= (mode & RTLD_GLOBAL) ? _RTLD_GLOBAL : 0;
995: flags |= (mode & RTLD_NOLOAD) ? _RTLD_NOLOAD : 0;
1.165 skrll 996:
1.137 skrll 997: nodelete = (mode & RTLD_NODELETE) ? true : false;
998: now = ((mode & RTLD_MODEMASK) == RTLD_NOW) ? true : false;
1.15 christos 999:
1000: _rtld_debug.r_state = RT_ADD;
1001: _rtld_debug_state();
1002:
1003: if (name == NULL) {
1004: obj = _rtld_objmain;
1.25 mycroft 1005: obj->refcount++;
1.67 mycroft 1006: } else
1.137 skrll 1007: obj = _rtld_load_library(name, _rtld_objmain, flags);
1008:
1.1 cgd 1009:
1.15 christos 1010: if (obj != NULL) {
1011: ++obj->dl_refcount;
1012: if (*old_obj_tail != NULL) { /* We loaded something new. */
1013: assert(*old_obj_tail == obj);
1014:
1.151 nonaka 1015: result = _rtld_load_needed_objects(obj, flags);
1016: if (result != -1) {
1017: Objlist_Entry *entry;
1018: _rtld_init_dag(obj);
1019: SIMPLEQ_FOREACH(entry, &obj->dagmembers, link) {
1020: result = _rtld_verify_object_versions(entry->obj);
1021: if (result == -1)
1022: break;
1023: }
1024: }
1025: if (result == -1 || _rtld_relocate_objects(obj,
1026: (now || obj->z_now)) == -1) {
1.148 joerg 1027: _rtld_unload_object(&mask, obj, false);
1.25 mycroft 1028: obj->dl_refcount--;
1.15 christos 1029: obj = NULL;
1.117 ad 1030: } else {
1.148 joerg 1031: _rtld_call_init_functions(&mask);
1.117 ad 1032: }
1.15 christos 1033: }
1.137 skrll 1034: if (obj != NULL) {
1035: if ((nodelete || obj->z_nodelete) && !obj->ref_nodel) {
1036: dbg(("dlopen obj %s nodelete", obj->path));
1037: _rtld_ref_dag(obj);
1038: obj->z_nodelete = obj->ref_nodel = true;
1039: }
1040: }
1.15 christos 1041: }
1042: _rtld_debug.r_state = RT_CONSISTENT;
1043: _rtld_debug_state();
1.1 cgd 1044:
1.148 joerg 1045: _rtld_exclusive_exit(&mask);
1.141 joerg 1046:
1.15 christos 1047: return obj;
1.31 erh 1048: }
1049:
1050: /*
1051: * Find a symbol in the main program.
1052: */
1053: void *
1.98 skrll 1054: _rtld_objmain_sym(const char *name)
1.31 erh 1055: {
1056: unsigned long hash;
1057: const Elf_Sym *def;
1058: const Obj_Entry *obj;
1.129 roy 1059: DoneList donelist;
1.31 erh 1060:
1061: hash = _rtld_elf_hash(name);
1062: obj = _rtld_objmain;
1.129 roy 1063: _rtld_donelist_init(&donelist);
1.31 erh 1064:
1.151 nonaka 1065: def = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, 0,
1066: NULL, &donelist);
1.129 roy 1067:
1.31 erh 1068: if (def != NULL)
1069: return obj->relocbase + def->st_value;
1.136 skrll 1070: return NULL;
1.1 cgd 1071: }
1072:
1.121 macallan 1073: #ifdef __powerpc__
1074: static void *
1075: hackish_return_address(void)
1076: {
1077: return __builtin_return_address(1);
1078: }
1079: #endif
1080:
1.141 joerg 1081: #ifdef __HAVE_FUNCTION_DESCRIPTORS
1.148 joerg 1082: #define lookup_mutex_enter() _rtld_exclusive_enter(&mask)
1083: #define lookup_mutex_exit() _rtld_exclusive_exit(&mask)
1.141 joerg 1084: #else
1085: #define lookup_mutex_enter() _rtld_shared_enter()
1086: #define lookup_mutex_exit() _rtld_shared_exit()
1087: #endif
1088:
1.151 nonaka 1089: static void *
1.155 joerg 1090: do_dlsym(void *handle, const char *name, const Ver_Entry *ventry, void *retaddr)
1.15 christos 1091: {
1.25 mycroft 1092: const Obj_Entry *obj;
1.92 mycroft 1093: unsigned long hash;
1.25 mycroft 1094: const Elf_Sym *def;
1.15 christos 1095: const Obj_Entry *defobj;
1.148 joerg 1096: DoneList donelist;
1.151 nonaka 1097: const u_int flags = SYMLOOK_DLSYM | SYMLOOK_IN_PLT;
1.148 joerg 1098: #ifdef __HAVE_FUNCTION_DESCRIPTORS
1099: sigset_t mask;
1100: #endif
1.141 joerg 1101:
1102: lookup_mutex_enter();
1103:
1.92 mycroft 1104: hash = _rtld_elf_hash(name);
1105: def = NULL;
1106: defobj = NULL;
1.165 skrll 1107:
1.93 christos 1108: switch ((intptr_t)handle) {
1109: case (intptr_t)NULL:
1110: case (intptr_t)RTLD_NEXT:
1111: case (intptr_t)RTLD_DEFAULT:
1112: case (intptr_t)RTLD_SELF:
1.30 christos 1113: if ((obj = _rtld_obj_from_addr(retaddr)) == NULL) {
1114: _rtld_error("Cannot determine caller's shared object");
1.141 joerg 1115: lookup_mutex_exit();
1.30 christos 1116: return NULL;
1117: }
1.93 christos 1118:
1119: switch ((intptr_t)handle) {
1120: case (intptr_t)NULL: /* Just the caller's shared object. */
1.151 nonaka 1121: def = _rtld_symlook_obj(name, hash, obj, flags, ventry);
1.92 mycroft 1122: defobj = obj;
1.93 christos 1123: break;
1124:
1125: case (intptr_t)RTLD_NEXT: /* Objects after callers */
1126: obj = obj->next;
1127: /*FALLTHROUGH*/
1128:
1129: case (intptr_t)RTLD_SELF: /* Caller included */
1130: for (; obj; obj = obj->next) {
1131: if ((def = _rtld_symlook_obj(name, hash, obj,
1.151 nonaka 1132: flags, ventry)) != NULL) {
1.92 mycroft 1133: defobj = obj;
1134: break;
1135: }
1136: }
1.93 christos 1137: break;
1138:
1139: case (intptr_t)RTLD_DEFAULT:
1140: def = _rtld_symlook_default(name, hash, obj, &defobj,
1.151 nonaka 1141: flags, ventry);
1.93 christos 1142: break;
1143:
1144: default:
1145: abort();
1.92 mycroft 1146: }
1.93 christos 1147: break;
1148:
1149: default:
1.141 joerg 1150: if ((obj = _rtld_dlcheck(handle)) == NULL) {
1151: lookup_mutex_exit();
1.30 christos 1152: return NULL;
1.141 joerg 1153: }
1154:
1.129 roy 1155: _rtld_donelist_init(&donelist);
1156:
1.92 mycroft 1157: if (obj->mainprog) {
1.93 christos 1158: /* Search main program and all libraries loaded by it */
1159: def = _rtld_symlook_list(name, hash, &_rtld_list_main,
1.151 nonaka 1160: &defobj, flags, ventry, &donelist);
1.92 mycroft 1161: } else {
1.122 skrll 1162: Needed_Entry fake;
1.129 roy 1163: DoneList depth;
1.122 skrll 1164:
1165: /* Search the object and all the libraries loaded by it. */
1166: fake.next = NULL;
1.124 christos 1167: fake.obj = __UNCONST(obj);
1.122 skrll 1168: fake.name = 0;
1.129 roy 1169:
1170: _rtld_donelist_init(&depth);
1.122 skrll 1171: def = _rtld_symlook_needed(name, hash, &fake, &defobj,
1.151 nonaka 1172: flags, ventry, &donelist, &depth);
1.25 mycroft 1173: }
1.129 roy 1174:
1.93 christos 1175: break;
1.30 christos 1176: }
1.165 skrll 1177:
1.51 fredette 1178: if (def != NULL) {
1.141 joerg 1179: void *p;
1.174 joerg 1180:
1181: if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
1182: #ifdef __HAVE_FUNCTION_DESCRIPTORS
1183: lookup_mutex_exit();
1184: _rtld_shared_enter();
1185: #endif
1186: p = (void *)_rtld_resolve_ifunc(defobj, def);
1187: _rtld_shared_exit();
1188: return p;
1189: }
1190:
1.51 fredette 1191: #ifdef __HAVE_FUNCTION_DESCRIPTORS
1.141 joerg 1192: if (ELF_ST_TYPE(def->st_info) == STT_FUNC) {
1.142 joerg 1193: p = (void *)_rtld_function_descriptor_alloc(defobj,
1194: def, 0);
1.141 joerg 1195: lookup_mutex_exit();
1196: return p;
1197: }
1.51 fredette 1198: #endif /* __HAVE_FUNCTION_DESCRIPTORS */
1.141 joerg 1199: p = defobj->relocbase + def->st_value;
1200: lookup_mutex_exit();
1201: return p;
1.51 fredette 1202: }
1.165 skrll 1203:
1.101 mycroft 1204: _rtld_error("Undefined symbol \"%s\"", name);
1.141 joerg 1205: lookup_mutex_exit();
1.92 mycroft 1206: return NULL;
1.25 mycroft 1207: }
1.1 cgd 1208:
1.151 nonaka 1209: __strong_alias(__dlsym,dlsym)
1210: void *
1211: dlsym(void *handle, const char *name)
1212: {
1.155 joerg 1213: void *retaddr;
1.151 nonaka 1214:
1215: dbg(("dlsym of %s in %p", name, handle));
1216:
1.155 joerg 1217: #ifdef __powerpc__
1218: retaddr = hackish_return_address();
1219: #else
1220: retaddr = __builtin_return_address(0);
1221: #endif
1222: return do_dlsym(handle, name, NULL, retaddr);
1.151 nonaka 1223: }
1224:
1225: __strong_alias(__dlvsym,dlvsym)
1226: void *
1227: dlvsym(void *handle, const char *name, const char *version)
1228: {
1229: Ver_Entry *ventry = NULL;
1230: Ver_Entry ver_entry;
1.155 joerg 1231: void *retaddr;
1.151 nonaka 1232:
1233: dbg(("dlvsym of %s@%s in %p", name, version ? version : NULL, handle));
1234:
1235: if (version != NULL) {
1236: ver_entry.name = version;
1237: ver_entry.file = NULL;
1238: ver_entry.hash = _rtld_elf_hash(version);
1239: ver_entry.flags = 0;
1240: ventry = &ver_entry;
1241: }
1.155 joerg 1242: #ifdef __powerpc__
1243: retaddr = hackish_return_address();
1244: #else
1245: retaddr = __builtin_return_address(0);
1246: #endif
1247: return do_dlsym(handle, name, ventry, retaddr);
1.151 nonaka 1248: }
1249:
1.106 thorpej 1250: __strong_alias(__dladdr,dladdr)
1.25 mycroft 1251: int
1.99 skrll 1252: dladdr(const void *addr, Dl_info *info)
1.25 mycroft 1253: {
1254: const Obj_Entry *obj;
1.51 fredette 1255: const Elf_Sym *def, *best_def;
1.25 mycroft 1256: void *symbol_addr;
1257: unsigned long symoffset;
1.149 joerg 1258: #ifdef __HAVE_FUNCTION_DESCRIPTORS
1259: sigset_t mask;
1260: #endif
1.141 joerg 1261:
1.144 joerg 1262: dbg(("dladdr of %p", addr));
1263:
1.141 joerg 1264: lookup_mutex_enter();
1265:
1.51 fredette 1266: #ifdef __HAVE_FUNCTION_DESCRIPTORS
1267: addr = _rtld_function_descriptor_function(addr);
1268: #endif /* __HAVE_FUNCTION_DESCRIPTORS */
1269:
1.25 mycroft 1270: obj = _rtld_obj_from_addr(addr);
1271: if (obj == NULL) {
1272: _rtld_error("No shared object contains address");
1.176 joerg 1273: lookup_mutex_exit();
1.25 mycroft 1274: return 0;
1275: }
1276: info->dli_fname = obj->path;
1277: info->dli_fbase = obj->mapbase;
1278: info->dli_saddr = (void *)0;
1279: info->dli_sname = NULL;
1.165 skrll 1280:
1.15 christos 1281: /*
1.25 mycroft 1282: * Walk the symbol list looking for the symbol whose address is
1283: * closest to the address sent in.
1284: */
1.51 fredette 1285: best_def = NULL;
1.25 mycroft 1286: for (symoffset = 0; symoffset < obj->nchains; symoffset++) {
1287: def = obj->symtab + symoffset;
1288:
1289: /*
1290: * For skip the symbol if st_shndx is either SHN_UNDEF or
1291: * SHN_COMMON.
1292: */
1293: if (def->st_shndx == SHN_UNDEF || def->st_shndx == SHN_COMMON)
1294: continue;
1295:
1296: /*
1297: * If the symbol is greater than the specified address, or if it
1298: * is further away from addr than the current nearest symbol,
1299: * then reject it.
1300: */
1301: symbol_addr = obj->relocbase + def->st_value;
1302: if (symbol_addr > addr || symbol_addr < info->dli_saddr)
1303: continue;
1304:
1305: /* Update our idea of the nearest symbol. */
1306: info->dli_sname = obj->strtab + def->st_name;
1307: info->dli_saddr = symbol_addr;
1.51 fredette 1308: best_def = def;
1.1 cgd 1309:
1.170 christos 1310:
1.25 mycroft 1311: /* Exact match? */
1312: if (info->dli_saddr == addr)
1313: break;
1314: }
1.51 fredette 1315:
1316: #ifdef __HAVE_FUNCTION_DESCRIPTORS
1317: if (best_def != NULL && ELF_ST_TYPE(best_def->st_info) == STT_FUNC)
1.165 skrll 1318: info->dli_saddr = (void *)_rtld_function_descriptor_alloc(obj,
1.51 fredette 1319: best_def, 0);
1.170 christos 1320: #else
1321: __USE(best_def);
1.51 fredette 1322: #endif /* __HAVE_FUNCTION_DESCRIPTORS */
1323:
1.141 joerg 1324: lookup_mutex_exit();
1.25 mycroft 1325: return 1;
1.1 cgd 1326: }
1327:
1.125 pooka 1328: __strong_alias(__dlinfo,dlinfo)
1329: int
1330: dlinfo(void *handle, int req, void *v)
1331: {
1332: const Obj_Entry *obj;
1333: void *retaddr;
1334:
1.144 joerg 1335: dbg(("dlinfo for %p %d", handle, req));
1336:
1.141 joerg 1337: _rtld_shared_enter();
1338:
1.125 pooka 1339: if (handle == RTLD_SELF) {
1340: #ifdef __powerpc__
1341: retaddr = hackish_return_address();
1342: #else
1343: retaddr = __builtin_return_address(0);
1344: #endif
1345: if ((obj = _rtld_obj_from_addr(retaddr)) == NULL) {
1346: _rtld_error("Cannot determine caller's shared object");
1.141 joerg 1347: _rtld_shared_exit();
1.125 pooka 1348: return -1;
1349: }
1350: } else {
1351: if ((obj = _rtld_dlcheck(handle)) == NULL) {
1.141 joerg 1352: _rtld_shared_exit();
1.125 pooka 1353: return -1;
1354: }
1355: }
1356:
1357: switch (req) {
1358: case RTLD_DI_LINKMAP:
1359: {
1360: const struct link_map **map = v;
1361:
1362: *map = &obj->linkmap;
1363: break;
1364: }
1365:
1366: default:
1367: _rtld_error("Invalid request");
1.141 joerg 1368: _rtld_shared_exit();
1.125 pooka 1369: return -1;
1370: }
1371:
1.141 joerg 1372: _rtld_shared_exit();
1.125 pooka 1373: return 0;
1374: }
1375:
1.131 skrll 1376: __strong_alias(__dl_iterate_phdr,dl_iterate_phdr);
1377: int
1378: dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), void *param)
1379: {
1380: struct dl_phdr_info phdr_info;
1381: const Obj_Entry *obj;
1382: int error = 0;
1383:
1.144 joerg 1384: dbg(("dl_iterate_phdr"));
1385:
1.141 joerg 1386: _rtld_shared_enter();
1387:
1.131 skrll 1388: for (obj = _rtld_objlist; obj != NULL; obj = obj->next) {
1389: phdr_info.dlpi_addr = (Elf_Addr)obj->relocbase;
1.166 christos 1390: /* XXX: wrong but not fixing it yet */
1.167 christos 1391: phdr_info.dlpi_name = SIMPLEQ_FIRST(&obj->names) ?
1392: SIMPLEQ_FIRST(&obj->names)->name : obj->path;
1.131 skrll 1393: phdr_info.dlpi_phdr = obj->phdr;
1394: phdr_info.dlpi_phnum = obj->phsize / sizeof(obj->phdr[0]);
1.140 joerg 1395: #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
1396: phdr_info.dlpi_tls_modid = obj->tlsindex;
1397: phdr_info.dlpi_tls_data = obj->tlsinit;
1398: #else
1.131 skrll 1399: phdr_info.dlpi_tls_modid = 0;
1400: phdr_info.dlpi_tls_data = 0;
1401: #endif
1402: phdr_info.dlpi_adds = _rtld_objloads;
1403: phdr_info.dlpi_subs = _rtld_objloads - _rtld_objcount;
1404:
1.141 joerg 1405: /* XXXlocking: exit point */
1.131 skrll 1406: error = callback(&phdr_info, sizeof(phdr_info), param);
1407: if (error)
1408: break;
1409: }
1410:
1.141 joerg 1411: _rtld_shared_exit();
1.131 skrll 1412: return error;
1413: }
1414:
1.1 cgd 1415: /*
1416: * Error reporting function. Use it like printf. If formats the message
1417: * into a buffer, and sets things up so that the next call to dlerror()
1418: * will return the message.
1419: */
1420: void
1.15 christos 1421: _rtld_error(const char *fmt,...)
1.1 cgd 1422: {
1.15 christos 1423: static char buf[512];
1424: va_list ap;
1.49 wiz 1425:
1.15 christos 1426: va_start(ap, fmt);
1427: xvsnprintf(buf, sizeof buf, fmt, ap);
1428: error_message = buf;
1429: va_end(ap);
1.1 cgd 1430: }
1.14 pk 1431:
1.1 cgd 1432: void
1.98 skrll 1433: _rtld_debug_state(void)
1.1 cgd 1434: {
1.175 skrll 1435: #if defined(__hppa__)
1436: __asm volatile("nop" ::: "memory");
1437: #endif
1.94 simonb 1438:
1.157 joerg 1439: /* Prevent optimizer from removing calls to this function */
1440: __insn_barrier();
1.1 cgd 1441: }
1442:
1443: void
1.98 skrll 1444: _rtld_linkmap_add(Obj_Entry *obj)
1.1 cgd 1445: {
1.15 christos 1446: struct link_map *l = &obj->linkmap;
1447: struct link_map *prev;
1.1 cgd 1448:
1.15 christos 1449: obj->linkmap.l_name = obj->path;
1.68 mycroft 1450: obj->linkmap.l_addr = obj->relocbase;
1.15 christos 1451: obj->linkmap.l_ld = obj->dynamic;
1.6 mhitch 1452: #ifdef __mips__
1.72 mycroft 1453: /* XXX This field is not standard and will be removed eventually. */
1.15 christos 1454: obj->linkmap.l_offs = obj->relocbase;
1.6 mhitch 1455: #endif
1.1 cgd 1456:
1.15 christos 1457: if (_rtld_debug.r_map == NULL) {
1458: _rtld_debug.r_map = l;
1459: return;
1460: }
1.109 skrll 1461:
1462: /*
1463: * Scan to the end of the list, but not past the entry for the
1464: * dynamic linker, which we want to keep at the very end.
1465: */
1466: for (prev = _rtld_debug.r_map;
1467: prev->l_next != NULL && prev->l_next != &_rtld_objself.linkmap;
1468: prev = prev->l_next);
1469:
1.15 christos 1470: l->l_prev = prev;
1.109 skrll 1471: l->l_next = prev->l_next;
1472: if (l->l_next != NULL)
1473: l->l_next->l_prev = l;
1.15 christos 1474: prev->l_next = l;
1.1 cgd 1475: }
1476:
1477: void
1.98 skrll 1478: _rtld_linkmap_delete(Obj_Entry *obj)
1.1 cgd 1479: {
1.15 christos 1480: struct link_map *l = &obj->linkmap;
1.1 cgd 1481:
1.15 christos 1482: if (l->l_prev == NULL) {
1483: if ((_rtld_debug.r_map = l->l_next) != NULL)
1484: l->l_next->l_prev = NULL;
1485: return;
1486: }
1487: if ((l->l_prev->l_next = l->l_next) != NULL)
1488: l->l_next->l_prev = l->l_prev;
1.25 mycroft 1489: }
1490:
1491: static Obj_Entry *
1492: _rtld_obj_from_addr(const void *addr)
1493: {
1494: Obj_Entry *obj;
1.165 skrll 1495:
1.25 mycroft 1496: for (obj = _rtld_objlist; obj != NULL; obj = obj->next) {
1497: if (addr < (void *) obj->mapbase)
1498: continue;
1.67 mycroft 1499: if (addr < (void *) (obj->mapbase + obj->mapsize))
1.25 mycroft 1500: return obj;
1501: }
1502: return NULL;
1503: }
1504:
1505: static void
1.117 ad 1506: _rtld_objlist_clear(Objlist *list)
1507: {
1508: while (!SIMPLEQ_EMPTY(list)) {
1509: Objlist_Entry* elm = SIMPLEQ_FIRST(list);
1510: SIMPLEQ_REMOVE_HEAD(list, link);
1511: xfree(elm);
1512: }
1513: }
1514:
1515: static void
1.98 skrll 1516: _rtld_objlist_remove(Objlist *list, Obj_Entry *obj)
1.25 mycroft 1517: {
1518: Objlist_Entry *elm;
1.165 skrll 1519:
1.25 mycroft 1520: if ((elm = _rtld_objlist_find(list, obj)) != NULL) {
1.50 lukem 1521: SIMPLEQ_REMOVE(list, elm, Struct_Objlist_Entry, link);
1.116 ad 1522: xfree(elm);
1.25 mycroft 1523: }
1.1 cgd 1524: }
1.141 joerg 1525:
1526: #define RTLD_EXCLUSIVE_MASK 0x80000000U
1527: static volatile unsigned int _rtld_mutex;
1528: static volatile unsigned int _rtld_waiter_exclusive;
1529: static volatile unsigned int _rtld_waiter_shared;
1530:
1531: void
1532: _rtld_shared_enter(void)
1533: {
1534: unsigned int cur;
1535: lwpid_t waiter, self = 0;
1536:
1537: membar_enter();
1538:
1539: for (;;) {
1540: cur = _rtld_mutex;
1541: /*
1542: * First check if we are currently not exclusively locked.
1543: */
1544: if ((cur & RTLD_EXCLUSIVE_MASK) == 0) {
1545: /* Yes, so increment use counter */
1546: if (atomic_cas_uint(&_rtld_mutex, cur, cur + 1) != cur)
1547: continue;
1.177 yamt 1548: membar_enter();
1.141 joerg 1549: return;
1550: }
1551: /*
1552: * Someone has an exclusive lock. Puts us on the waiter list.
1553: */
1554: if (!self)
1555: self = _lwp_self();
1556: if (cur == (self | RTLD_EXCLUSIVE_MASK)) {
1557: if (_rtld_mutex_may_recurse)
1558: return;
1559: _rtld_error("dead lock detected");
1560: _rtld_die();
1561: }
1562: waiter = atomic_swap_uint(&_rtld_waiter_shared, self);
1563: /*
1564: * Check for race against _rtld_exclusive_exit before sleeping.
1565: */
1.177 yamt 1566: membar_sync();
1.141 joerg 1567: if ((_rtld_mutex & RTLD_EXCLUSIVE_MASK) ||
1568: _rtld_waiter_exclusive)
1.172 joerg 1569: _lwp_park(CLOCK_REALTIME, 0, NULL, 0,
1570: __UNVOLATILE(&_rtld_mutex), NULL);
1.141 joerg 1571: /* Try to remove us from the waiter list. */
1572: atomic_cas_uint(&_rtld_waiter_shared, self, 0);
1573: if (waiter)
1574: _lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex));
1575: }
1576: }
1577:
1578: void
1579: _rtld_shared_exit(void)
1580: {
1581: lwpid_t waiter;
1582:
1583: /*
1584: * Shared lock taken after an exclusive lock.
1585: * Just assume this is a partial recursion.
1586: */
1587: if (_rtld_mutex & RTLD_EXCLUSIVE_MASK)
1588: return;
1589:
1590: /*
1591: * Wakeup LWPs waiting for an exclusive lock if this is the last
1592: * LWP on the shared lock.
1593: */
1.177 yamt 1594: membar_exit();
1.141 joerg 1595: if (atomic_dec_uint_nv(&_rtld_mutex))
1596: return;
1.177 yamt 1597: membar_sync();
1.141 joerg 1598: if ((waiter = _rtld_waiter_exclusive) != 0)
1599: _lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex));
1600: }
1601:
1602: void
1.148 joerg 1603: _rtld_exclusive_enter(sigset_t *mask)
1.141 joerg 1604: {
1605: lwpid_t waiter, self = _lwp_self();
1606: unsigned int locked_value = (unsigned int)self | RTLD_EXCLUSIVE_MASK;
1607: unsigned int cur;
1.148 joerg 1608: sigset_t blockmask;
1609:
1610: sigfillset(&blockmask);
1.153 christos 1611: sigdelset(&blockmask, SIGTRAP); /* Allow the debugger */
1.148 joerg 1612: sigprocmask(SIG_BLOCK, &blockmask, mask);
1.141 joerg 1613:
1614: for (;;) {
1.177 yamt 1615: if (atomic_cas_uint(&_rtld_mutex, 0, locked_value) == 0) {
1616: membar_enter();
1.141 joerg 1617: break;
1.177 yamt 1618: }
1.141 joerg 1619: waiter = atomic_swap_uint(&_rtld_waiter_exclusive, self);
1.177 yamt 1620: membar_sync();
1.141 joerg 1621: cur = _rtld_mutex;
1622: if (cur == locked_value) {
1623: _rtld_error("dead lock detected");
1624: _rtld_die();
1625: }
1626: if (cur)
1.172 joerg 1627: _lwp_park(CLOCK_REALTIME, 0, NULL, 0,
1628: __UNVOLATILE(&_rtld_mutex), NULL);
1.141 joerg 1629: atomic_cas_uint(&_rtld_waiter_exclusive, self, 0);
1630: if (waiter)
1631: _lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex));
1632: }
1633: }
1634:
1635: void
1.148 joerg 1636: _rtld_exclusive_exit(sigset_t *mask)
1.141 joerg 1637: {
1638: lwpid_t waiter;
1639:
1.177 yamt 1640: membar_exit();
1.141 joerg 1641: _rtld_mutex = 0;
1.177 yamt 1642: membar_sync();
1.141 joerg 1643: if ((waiter = _rtld_waiter_exclusive) != 0)
1644: _lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex));
1645:
1646: if ((waiter = _rtld_waiter_shared) != 0)
1647: _lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex));
1648:
1.148 joerg 1649: sigprocmask(SIG_SETMASK, mask, NULL);
1.141 joerg 1650: }
CVSweb <webmaster@jp.NetBSD.org>