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