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