Thu Apr 16 14:39:58 2020 UTC ()
Introduce intermediate locking for fork, so that the dynamic linker is
in a consistent state. This most importantly avoids races between dlopen
and friends and fork, potentially resulting in dead locks in the child
when it itself tries to acquire locks.


(joerg)
diff -r1.12 -r1.13 src/lib/libc/gen/pthread_atfork.c
diff -r1.203 -r1.204 src/libexec/ld.elf_so/rtld.c
diff -r1.138 -r1.139 src/libexec/ld.elf_so/rtld.h
diff -r1.2 -r1.3 src/libexec/ld.elf_so/symbols.map

cvs diff -r1.12 -r1.13 src/lib/libc/gen/pthread_atfork.c (switch to unified diff)

--- src/lib/libc/gen/pthread_atfork.c 2020/02/01 18:14:16 1.12
+++ src/lib/libc/gen/pthread_atfork.c 2020/04/16 14:39:58 1.13
@@ -1,205 +1,212 @@ @@ -1,205 +1,212 @@
1/* $NetBSD: pthread_atfork.c,v 1.12 2020/02/01 18:14:16 kamil Exp $ */ 1/* $NetBSD: pthread_atfork.c,v 1.13 2020/04/16 14:39:58 joerg Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2002 The NetBSD Foundation, Inc. 4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Nathan J. Williams. 8 * by Nathan J. Williams.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33#if defined(LIBC_SCCS) && !defined(lint) 33#if defined(LIBC_SCCS) && !defined(lint)
34__RCSID("$NetBSD: pthread_atfork.c,v 1.12 2020/02/01 18:14:16 kamil Exp $"); 34__RCSID("$NetBSD: pthread_atfork.c,v 1.13 2020/04/16 14:39:58 joerg Exp $");
35#endif /* LIBC_SCCS and not lint */ 35#endif /* LIBC_SCCS and not lint */
36 36
37#include "namespace.h" 37#include "namespace.h"
38 38
39#include <errno.h> 39#include <errno.h>
40#include <stdlib.h> 40#include <stdlib.h>
41#include <unistd.h> 41#include <unistd.h>
42#include <sys/queue.h> 42#include <sys/queue.h>
43#include "reentrant.h" 43#include "reentrant.h"
44 44
45#ifdef __weak_alias 45#ifdef __weak_alias
46__weak_alias(pthread_atfork, _pthread_atfork) 46__weak_alias(pthread_atfork, _pthread_atfork)
47__weak_alias(fork, _fork) 47__weak_alias(fork, _fork)
48#endif /* __weak_alias */ 48#endif /* __weak_alias */
49 49
50pid_t __fork(void); /* XXX */ 50pid_t __fork(void); /* XXX */
 51pid_t __atomic_fork(void) __weak; /* XXX */
 52
 53pid_t
 54__atomic_fork(void)
 55{
 56 return __fork();
 57}
51 58
52struct atfork_callback { 59struct atfork_callback {
53 SIMPLEQ_ENTRY(atfork_callback) next; 60 SIMPLEQ_ENTRY(atfork_callback) next;
54 void (*fn)(void); 61 void (*fn)(void);
55}; 62};
56 63
57/* 64/*
58 * Hypothetically, we could protect the queues with a rwlock which is 65 * Hypothetically, we could protect the queues with a rwlock which is
59 * write-locked by pthread_atfork() and read-locked by fork(), but 66 * write-locked by pthread_atfork() and read-locked by fork(), but
60 * since the intended use of the functions is obtaining locks to hold 67 * since the intended use of the functions is obtaining locks to hold
61 * across the fork, forking is going to be serialized anyway. 68 * across the fork, forking is going to be serialized anyway.
62 */ 69 */
63static struct atfork_callback atfork_builtin; 70static struct atfork_callback atfork_builtin;
64#ifdef _REENTRANT 71#ifdef _REENTRANT
65static mutex_t atfork_lock = MUTEX_INITIALIZER; 72static mutex_t atfork_lock = MUTEX_INITIALIZER;
66#endif 73#endif
67SIMPLEQ_HEAD(atfork_callback_q, atfork_callback); 74SIMPLEQ_HEAD(atfork_callback_q, atfork_callback);
68 75
69static struct atfork_callback_q prepareq = SIMPLEQ_HEAD_INITIALIZER(prepareq); 76static struct atfork_callback_q prepareq = SIMPLEQ_HEAD_INITIALIZER(prepareq);
70static struct atfork_callback_q parentq = SIMPLEQ_HEAD_INITIALIZER(parentq); 77static struct atfork_callback_q parentq = SIMPLEQ_HEAD_INITIALIZER(parentq);
71static struct atfork_callback_q childq = SIMPLEQ_HEAD_INITIALIZER(childq); 78static struct atfork_callback_q childq = SIMPLEQ_HEAD_INITIALIZER(childq);
72 79
73static struct atfork_callback * 80static struct atfork_callback *
74af_alloc(void) 81af_alloc(void)
75{ 82{
76 83
77 if (atfork_builtin.fn == NULL) 84 if (atfork_builtin.fn == NULL)
78 return &atfork_builtin; 85 return &atfork_builtin;
79 86
80 return malloc(sizeof(atfork_builtin)); 87 return malloc(sizeof(atfork_builtin));
81} 88}
82 89
83static void 90static void
84af_free(struct atfork_callback *af) 91af_free(struct atfork_callback *af)
85{ 92{
86 93
87 if (af != &atfork_builtin) 94 if (af != &atfork_builtin)
88 free(af); 95 free(af);
89} 96}
90 97
91int 98int
92pthread_atfork(void (*prepare)(void), void (*parent)(void), 99pthread_atfork(void (*prepare)(void), void (*parent)(void),
93 void (*child)(void)) 100 void (*child)(void))
94{ 101{
95 struct atfork_callback *newprepare, *newparent, *newchild; 102 struct atfork_callback *newprepare, *newparent, *newchild;
96 103
97 newprepare = newparent = newchild = NULL; 104 newprepare = newparent = newchild = NULL;
98 105
99 mutex_lock(&atfork_lock); 106 mutex_lock(&atfork_lock);
100 if (prepare != NULL) { 107 if (prepare != NULL) {
101 newprepare = af_alloc(); 108 newprepare = af_alloc();
102 if (newprepare == NULL) { 109 if (newprepare == NULL) {
103 mutex_unlock(&atfork_lock); 110 mutex_unlock(&atfork_lock);
104 return ENOMEM; 111 return ENOMEM;
105 } 112 }
106 newprepare->fn = prepare; 113 newprepare->fn = prepare;
107 } 114 }
108 115
109 if (parent != NULL) { 116 if (parent != NULL) {
110 newparent = af_alloc(); 117 newparent = af_alloc();
111 if (newparent == NULL) { 118 if (newparent == NULL) {
112 if (newprepare != NULL) 119 if (newprepare != NULL)
113 af_free(newprepare); 120 af_free(newprepare);
114 mutex_unlock(&atfork_lock); 121 mutex_unlock(&atfork_lock);
115 return ENOMEM; 122 return ENOMEM;
116 } 123 }
117 newparent->fn = parent; 124 newparent->fn = parent;
118 } 125 }
119 126
120 if (child != NULL) { 127 if (child != NULL) {
121 newchild = af_alloc(); 128 newchild = af_alloc();
122 if (newchild == NULL) { 129 if (newchild == NULL) {
123 if (newprepare != NULL) 130 if (newprepare != NULL)
124 af_free(newprepare); 131 af_free(newprepare);
125 if (newparent != NULL) 132 if (newparent != NULL)
126 af_free(newparent); 133 af_free(newparent);
127 mutex_unlock(&atfork_lock); 134 mutex_unlock(&atfork_lock);
128 return ENOMEM; 135 return ENOMEM;
129 } 136 }
130 newchild->fn = child; 137 newchild->fn = child;
131 } 138 }
132 139
133 /* 140 /*
134 * The order in which the functions are called is specified as 141 * The order in which the functions are called is specified as
135 * LIFO for the prepare handler and FIFO for the others; insert 142 * LIFO for the prepare handler and FIFO for the others; insert
136 * at the head and tail as appropriate so that SIMPLEQ_FOREACH() 143 * at the head and tail as appropriate so that SIMPLEQ_FOREACH()
137 * produces the right order. 144 * produces the right order.
138 */ 145 */
139 if (prepare) 146 if (prepare)
140 SIMPLEQ_INSERT_HEAD(&prepareq, newprepare, next); 147 SIMPLEQ_INSERT_HEAD(&prepareq, newprepare, next);
141 if (parent) 148 if (parent)
142 SIMPLEQ_INSERT_TAIL(&parentq, newparent, next); 149 SIMPLEQ_INSERT_TAIL(&parentq, newparent, next);
143 if (child) 150 if (child)
144 SIMPLEQ_INSERT_TAIL(&childq, newchild, next); 151 SIMPLEQ_INSERT_TAIL(&childq, newchild, next);
145 mutex_unlock(&atfork_lock); 152 mutex_unlock(&atfork_lock);
146 153
147 return 0; 154 return 0;
148} 155}
149 156
150pid_t 157pid_t
151fork(void) 158fork(void)
152{ 159{
153 struct atfork_callback *iter; 160 struct atfork_callback *iter;
154 pid_t ret; 161 pid_t ret;
155 162
156 mutex_lock(&atfork_lock); 163 mutex_lock(&atfork_lock);
157 SIMPLEQ_FOREACH(iter, &prepareq, next) 164 SIMPLEQ_FOREACH(iter, &prepareq, next)
158 (*iter->fn)(); 165 (*iter->fn)();
159 166
160 ret = __fork(); 167 ret = __atomic_fork();
161 168
162 if (ret != 0) { 169 if (ret != 0) {
163 /* 170 /*
164 * We are the parent. It doesn't matter here whether 171 * We are the parent. It doesn't matter here whether
165 * the fork call succeeded or failed. 172 * the fork call succeeded or failed.
166 */ 173 */
167 SIMPLEQ_FOREACH(iter, &parentq, next) 174 SIMPLEQ_FOREACH(iter, &parentq, next)
168 (*iter->fn)(); 175 (*iter->fn)();
169 mutex_unlock(&atfork_lock); 176 mutex_unlock(&atfork_lock);
170 } else { 177 } else {
171 /* We are the child */ 178 /* We are the child */
172 SIMPLEQ_FOREACH(iter, &childq, next) 179 SIMPLEQ_FOREACH(iter, &childq, next)
173 (*iter->fn)(); 180 (*iter->fn)();
174 /* 181 /*
175 * Note: We are explicitly *not* unlocking 182 * Note: We are explicitly *not* unlocking
176 * atfork_lock. Unlocking atfork_lock is problematic, 183 * atfork_lock. Unlocking atfork_lock is problematic,
177 * because if any threads in the parent blocked on it 184 * because if any threads in the parent blocked on it
178 * between the initial lock and the fork() syscall, 185 * between the initial lock and the fork() syscall,
179 * unlocking in the child will try to schedule 186 * unlocking in the child will try to schedule
180 * threads, and either the internal mutex interlock or 187 * threads, and either the internal mutex interlock or
181 * the runqueue spinlock could have been held at the 188 * the runqueue spinlock could have been held at the
182 * moment of fork(). Since the other threads do not 189 * moment of fork(). Since the other threads do not
183 * exist in this process, the spinlock will never be 190 * exist in this process, the spinlock will never be
184 * unlocked, and we would wedge. 191 * unlocked, and we would wedge.
185 * Instead, we reinitialize atfork_lock, since we know 192 * Instead, we reinitialize atfork_lock, since we know
186 * that the state of the atfork lists is consistent here, 193 * that the state of the atfork lists is consistent here,
187 * and that there are no other threads to be affected by 194 * and that there are no other threads to be affected by
188 * the forcible cleaning of the queue. 195 * the forcible cleaning of the queue.
189 * This permits double-forking to work, although 196 * This permits double-forking to work, although
190 * it requires knowing that it's "safe" to initialize 197 * it requires knowing that it's "safe" to initialize
191 * a locked mutex in this context. 198 * a locked mutex in this context.
192 * 199 *
193 * The problem exists for users of this interface, 200 * The problem exists for users of this interface,
194 * too, since the intented use of pthread_atfork() is 201 * too, since the intented use of pthread_atfork() is
195 * to acquire locks across the fork call to ensure 202 * to acquire locks across the fork call to ensure
196 * that the child sees consistent state. There's not 203 * that the child sees consistent state. There's not
197 * much that can usefully be done in a child handler, 204 * much that can usefully be done in a child handler,
198 * and conventional wisdom discourages using them, but 205 * and conventional wisdom discourages using them, but
199 * they're part of the interface, so here we are... 206 * they're part of the interface, so here we are...
200 */ 207 */
201 mutex_init(&atfork_lock, NULL); 208 mutex_init(&atfork_lock, NULL);
202 } 209 }
203 210
204 return ret; 211 return ret;
205} 212}

cvs diff -r1.203 -r1.204 src/libexec/ld.elf_so/rtld.c (switch to unified diff)

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

cvs diff -r1.138 -r1.139 src/libexec/ld.elf_so/rtld.h (switch to unified diff)

--- src/libexec/ld.elf_so/rtld.h 2020/02/29 04:24:33 1.138
+++ src/libexec/ld.elf_so/rtld.h 2020/04/16 14:39:58 1.139
@@ -1,524 +1,526 @@ @@ -1,524 +1,526 @@
1/* $NetBSD: rtld.h,v 1.138 2020/02/29 04:24:33 kamil Exp $ */ 1/* $NetBSD: rtld.h,v 1.139 2020/04/16 14:39:58 joerg Exp $ */
2 2
3/* 3/*
4 * Copyright 1996 John D. Polstra. 4 * Copyright 1996 John D. Polstra.
5 * Copyright 1996 Matt Thomas <matt@3am-software.com> 5 * Copyright 1996 Matt Thomas <matt@3am-software.com>
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software 16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement: 17 * must display the following acknowledgement:
18 * This product includes software developed by John Polstra. 18 * This product includes software developed by John Polstra.
19 * 4. The name of the author may not be used to endorse or promote products 19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission. 20 * derived from this software without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */ 32 */
33 33
34#ifndef RTLD_H 34#ifndef RTLD_H
35#define RTLD_H 35#define RTLD_H
36 36
37#include <dlfcn.h> 37#include <dlfcn.h>
38#include <signal.h> 38#include <signal.h>
39#include <stdbool.h> 39#include <stdbool.h>
40#include <stddef.h> 40#include <stddef.h>
41#include <sys/param.h> 41#include <sys/param.h>
42#include <sys/types.h> 42#include <sys/types.h>
43#include <sys/queue.h> 43#include <sys/queue.h>
44#include <sys/exec_elf.h> 44#include <sys/exec_elf.h>
45#include <sys/tls.h> 45#include <sys/tls.h>
46#include "rtldenv.h" 46#include "rtldenv.h"
47#include "link.h" 47#include "link.h"
48 48
49#if defined(_RTLD_SOURCE) 49#if defined(_RTLD_SOURCE)
50 50
51#if defined(__ARM_EABI__) && !defined(__ARM_DWARF_EH__) 51#if defined(__ARM_EABI__) && !defined(__ARM_DWARF_EH__)
52#include "unwind.h" 52#include "unwind.h"
53#endif 53#endif
54 54
55#ifndef RTLD_DEFAULT_LIBRARY_PATH 55#ifndef RTLD_DEFAULT_LIBRARY_PATH
56#define RTLD_DEFAULT_LIBRARY_PATH "/usr/lib" 56#define RTLD_DEFAULT_LIBRARY_PATH "/usr/lib"
57#endif 57#endif
58#define _PATH_LD_HINTS "/etc/ld.so.conf" 58#define _PATH_LD_HINTS "/etc/ld.so.conf"
59 59
60extern size_t _rtld_pagesz; 60extern size_t _rtld_pagesz;
61 61
62#define round_down(x) ((x) & ~(_rtld_pagesz - 1)) 62#define round_down(x) ((x) & ~(_rtld_pagesz - 1))
63#define round_up(x) round_down((x) + _rtld_pagesz - 1) 63#define round_up(x) round_down((x) + _rtld_pagesz - 1)
64 64
65#define NEW(type) ((type *) xmalloc(sizeof(type))) 65#define NEW(type) ((type *) xmalloc(sizeof(type)))
66#define CNEW(type) ((type *) xcalloc(sizeof(type))) 66#define CNEW(type) ((type *) xcalloc(sizeof(type)))
67 67
68/* 68/*
69 * Fill in a DoneList with an allocation large enough to hold all of 69 * Fill in a DoneList with an allocation large enough to hold all of
70 * the currently-loaded objects. Keep this in a macro since it calls 70 * the currently-loaded objects. Keep this in a macro since it calls
71 * alloca and we want that to occur within the scope of the caller. 71 * alloca and we want that to occur within the scope of the caller.
72 */ 72 */
73#define _rtld_donelist_init(dlp) \ 73#define _rtld_donelist_init(dlp) \
74 ((dlp)->num_alloc = _rtld_objcount, \ 74 ((dlp)->num_alloc = _rtld_objcount, \
75 (dlp)->objs = alloca((dlp)->num_alloc * sizeof((dlp)->objs[0])), \ 75 (dlp)->objs = alloca((dlp)->num_alloc * sizeof((dlp)->objs[0])), \
76 assert((dlp)->objs != NULL), \ 76 assert((dlp)->objs != NULL), \
77 (dlp)->num_used = 0) 77 (dlp)->num_used = 0)
78 78
79 79
80typedef struct Struct_Elf_Hash { 80typedef struct Struct_Elf_Hash {
81 unsigned long sysv; 81 unsigned long sysv;
82 unsigned long gnu; 82 unsigned long gnu;
83} Elf_Hash; 83} Elf_Hash;
84#endif /* _RTLD_SOURCE */ 84#endif /* _RTLD_SOURCE */
85 85
86/* 86/*
87 * C++ has mandated the use of the following keywords for its new boolean 87 * C++ has mandated the use of the following keywords for its new boolean
88 * type. We might as well follow their lead. 88 * type. We might as well follow their lead.
89 */ 89 */
90struct Struct_Obj_Entry; 90struct Struct_Obj_Entry;
91 91
92typedef struct Struct_Objlist_Entry { 92typedef struct Struct_Objlist_Entry {
93 SIMPLEQ_ENTRY(Struct_Objlist_Entry) link; 93 SIMPLEQ_ENTRY(Struct_Objlist_Entry) link;
94 struct Struct_Obj_Entry *obj; 94 struct Struct_Obj_Entry *obj;
95} Objlist_Entry; 95} Objlist_Entry;
96 96
97typedef SIMPLEQ_HEAD(Struct_Objlist, Struct_Objlist_Entry) Objlist; 97typedef SIMPLEQ_HEAD(Struct_Objlist, Struct_Objlist_Entry) Objlist;
98 98
99typedef struct Struct_Name_Entry { 99typedef struct Struct_Name_Entry {
100 SIMPLEQ_ENTRY(Struct_Name_Entry) link; 100 SIMPLEQ_ENTRY(Struct_Name_Entry) link;
101 char name[1]; 101 char name[1];
102} Name_Entry; 102} Name_Entry;
103 103
104typedef struct Struct_Needed_Entry { 104typedef struct Struct_Needed_Entry {
105 struct Struct_Needed_Entry *next; 105 struct Struct_Needed_Entry *next;
106 struct Struct_Obj_Entry *obj; 106 struct Struct_Obj_Entry *obj;
107 unsigned long name; /* Offset of name in string table */ 107 unsigned long name; /* Offset of name in string table */
108} Needed_Entry; 108} Needed_Entry;
109 109
110typedef struct _rtld_search_path_t { 110typedef struct _rtld_search_path_t {
111 struct _rtld_search_path_t *sp_next; 111 struct _rtld_search_path_t *sp_next;
112 const char *sp_path; 112 const char *sp_path;
113 size_t sp_pathlen; 113 size_t sp_pathlen;
114} Search_Path; 114} Search_Path;
115 115
116typedef struct Struct_Ver_Entry { 116typedef struct Struct_Ver_Entry {
117 Elf_Word hash; 117 Elf_Word hash;
118 u_int flags; 118 u_int flags;
119 const char *name; 119 const char *name;
120 const char *file; 120 const char *file;
121} Ver_Entry; 121} Ver_Entry;
122 122
123/* Ver_Entry.flags */ 123/* Ver_Entry.flags */
124#define VER_INFO_HIDDEN 0x01 124#define VER_INFO_HIDDEN 0x01
125 125
126#define RTLD_MAX_ENTRY 10 126#define RTLD_MAX_ENTRY 10
127#define RTLD_MAX_LIBRARY 4 127#define RTLD_MAX_LIBRARY 4
128#define RTLD_MAX_CTL 2 128#define RTLD_MAX_CTL 2
129typedef struct _rtld_library_xform_t { 129typedef struct _rtld_library_xform_t {
130 struct _rtld_library_xform_t *next; 130 struct _rtld_library_xform_t *next;
131 char *name; 131 char *name;
132 const char *ctlname; 132 const char *ctlname;
133 struct { 133 struct {
134 char *value; 134 char *value;
135 char *library[RTLD_MAX_LIBRARY]; 135 char *library[RTLD_MAX_LIBRARY];
136 } entry[RTLD_MAX_ENTRY]; 136 } entry[RTLD_MAX_ENTRY];
137} Library_Xform; 137} Library_Xform;
138 138
139/* 139/*
140 * Shared object descriptor. 140 * Shared object descriptor.
141 * 141 *
142 * Items marked with "(%)" are dynamically allocated, and must be freed 142 * Items marked with "(%)" are dynamically allocated, and must be freed
143 * when the structure is destroyed. 143 * when the structure is destroyed.
144 */ 144 */
145 145
146typedef void (*fptr_t)(void); 146typedef void (*fptr_t)(void);
147 147
148typedef struct Struct_Obj_Entry { 148typedef struct Struct_Obj_Entry {
149 struct Struct_Obj_Entry *next; 149 struct Struct_Obj_Entry *next;
150 char *path; /* Pathname of underlying file (%) */ 150 char *path; /* Pathname of underlying file (%) */
151 int refcount; 151 int refcount;
152 int dl_refcount; /* Number of times loaded by dlopen */ 152 int dl_refcount; /* Number of times loaded by dlopen */
153 153
154 /* These items are computed by map_object() or by digest_phdr(). */ 154 /* These items are computed by map_object() or by digest_phdr(). */
155 caddr_t mapbase; /* Base address of mapped region */ 155 caddr_t mapbase; /* Base address of mapped region */
156 size_t mapsize; /* Size of mapped region in bytes */ 156 size_t mapsize; /* Size of mapped region in bytes */
157 size_t textsize; /* Size of text segment in bytes */ 157 size_t textsize; /* Size of text segment in bytes */
158 Elf_Addr vaddrbase; /* Base address in shared object file */ 158 Elf_Addr vaddrbase; /* Base address in shared object file */
159 caddr_t relocbase; /* Reloc const = mapbase - *vaddrbase */ 159 caddr_t relocbase; /* Reloc const = mapbase - *vaddrbase */
160 Elf_Dyn *dynamic; /* Dynamic section */ 160 Elf_Dyn *dynamic; /* Dynamic section */
161 caddr_t entry; /* Entry point */ 161 caddr_t entry; /* Entry point */
162 const Elf_Phdr *phdr; /* Program header (may be xmalloc'ed) */ 162 const Elf_Phdr *phdr; /* Program header (may be xmalloc'ed) */
163 size_t phsize; /* Size of program header in bytes */ 163 size_t phsize; /* Size of program header in bytes */
164 164
165 /* Items from the dynamic section. */ 165 /* Items from the dynamic section. */
166 Elf_Addr *pltgot; /* PLTGOT table */ 166 Elf_Addr *pltgot; /* PLTGOT table */
167 const Elf_Rel *rel; /* Relocation entries */ 167 const Elf_Rel *rel; /* Relocation entries */
168 const Elf_Rel *rellim; /* Limit of Relocation entries */ 168 const Elf_Rel *rellim; /* Limit of Relocation entries */
169 const Elf_Rela *rela; /* Relocation entries */ 169 const Elf_Rela *rela; /* Relocation entries */
170 const Elf_Rela *relalim; /* Limit of Relocation entries */ 170 const Elf_Rela *relalim; /* Limit of Relocation entries */
171 const Elf_Rel *pltrel; /* PLT relocation entries */ 171 const Elf_Rel *pltrel; /* PLT relocation entries */
172 const Elf_Rel *pltrellim; /* Limit of PLT relocation entries */ 172 const Elf_Rel *pltrellim; /* Limit of PLT relocation entries */
173 const Elf_Rela *pltrela; /* PLT relocation entries */ 173 const Elf_Rela *pltrela; /* PLT relocation entries */
174 const Elf_Rela *pltrelalim; /* Limit of PLT relocation entries */ 174 const Elf_Rela *pltrelalim; /* Limit of PLT relocation entries */
175 const Elf_Sym *symtab; /* Symbol table */ 175 const Elf_Sym *symtab; /* Symbol table */
176 const char *strtab; /* String table */ 176 const char *strtab; /* String table */
177 unsigned long strsize; /* Size in bytes of string table */ 177 unsigned long strsize; /* Size in bytes of string table */
178#if defined(__mips__) || defined(__riscv__) 178#if defined(__mips__) || defined(__riscv__)
179 Elf_Word local_gotno; /* Number of local GOT entries */ 179 Elf_Word local_gotno; /* Number of local GOT entries */
180 Elf_Word symtabno; /* Number of dynamic symbols */ 180 Elf_Word symtabno; /* Number of dynamic symbols */
181 Elf_Word gotsym; /* First dynamic symbol in GOT */ 181 Elf_Word gotsym; /* First dynamic symbol in GOT */
182#endif 182#endif
183 183
184 /* SysV Hash fields */ 184 /* SysV Hash fields */
185 const Elf_Symindx *buckets; /* Hash table buckets array */ 185 const Elf_Symindx *buckets; /* Hash table buckets array */
186 unsigned long unused1; /* Used to be nbuckets */ 186 unsigned long unused1; /* Used to be nbuckets */
187 const Elf_Symindx *chains; /* Hash table chain array */ 187 const Elf_Symindx *chains; /* Hash table chain array */
188 unsigned long nchains; /* Number of chains */ 188 unsigned long nchains; /* Number of chains */
189 189
190 Search_Path *rpaths; /* Search path specified in object */ 190 Search_Path *rpaths; /* Search path specified in object */
191 Needed_Entry *needed; /* Shared objects needed by this (%) */ 191 Needed_Entry *needed; /* Shared objects needed by this (%) */
192 192
193 Elf_Addr init; /* Initialization function to call */ 193 Elf_Addr init; /* Initialization function to call */
194 Elf_Addr fini; /* Termination function to call */ 194 Elf_Addr fini; /* Termination function to call */
195 195
196 u_int32_t mainprog:1, /* True if this is the main program */ 196 u_int32_t mainprog:1, /* True if this is the main program */
197 rtld:1, /* True if this is the dynamic linker */ 197 rtld:1, /* True if this is the dynamic linker */
198 textrel:1, /* True if there are relocations to 198 textrel:1, /* True if there are relocations to
199 * text seg */ 199 * text seg */
200 symbolic:1, /* True if generated with 200 symbolic:1, /* True if generated with
201 * "-Bsymbolic" */ 201 * "-Bsymbolic" */
202 printed:1, /* True if ldd has printed it */ 202 printed:1, /* True if ldd has printed it */
203 isdynamic:1, /* True if this is a pure PIC object */ 203 isdynamic:1, /* True if this is a pure PIC object */
204 mainref:1, /* True if on _rtld_list_main */ 204 mainref:1, /* True if on _rtld_list_main */
205 globalref:1, /* True if on _rtld_list_global */ 205 globalref:1, /* True if on _rtld_list_global */
206 init_done:1, /* True if .init has been added */ 206 init_done:1, /* True if .init has been added */
207 init_called:1, /* True if .init function has been 207 init_called:1, /* True if .init function has been
208 * called */ 208 * called */
209 fini_called:1, /* True if .fini function has been 209 fini_called:1, /* True if .fini function has been
210 * called */ 210 * called */
211 z_now:1, /* True if object's symbols should be 211 z_now:1, /* True if object's symbols should be
212 bound immediately */ 212 bound immediately */
213 z_nodelete:1, /* True if object should never be 213 z_nodelete:1, /* True if object should never be
214 unloaded */ 214 unloaded */
215 z_initfirst:1, /* True if object's .init/.fini take 215 z_initfirst:1, /* True if object's .init/.fini take
216 * priority over others */ 216 * priority over others */
217 z_noopen:1, /* True if object should never be 217 z_noopen:1, /* True if object should never be
218 dlopen'ed */ 218 dlopen'ed */
219 phdr_loaded:1, /* Phdr is loaded and doesn't need to 219 phdr_loaded:1, /* Phdr is loaded and doesn't need to
220 * be freed. */ 220 * be freed. */
221#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) 221#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
222 tls_done:1, /* True if static TLS offset 222 tls_done:1, /* True if static TLS offset
223 * has been allocated */ 223 * has been allocated */
224#endif 224#endif
225 ref_nodel:1, /* Refcount increased to prevent dlclose */ 225 ref_nodel:1, /* Refcount increased to prevent dlclose */
226 sysv_hash:1, /* SysV Hash available */ 226 sysv_hash:1, /* SysV Hash available */
227 gnu_hash:1; /* GNU Hash available */ 227 gnu_hash:1; /* GNU Hash available */
228 228
229 struct link_map linkmap; /* for GDB */ 229 struct link_map linkmap; /* for GDB */
230 230
231 /* These items are computed by map_object() or by digest_phdr(). */ 231 /* These items are computed by map_object() or by digest_phdr(). */
232 const char *interp; /* Pathname of the interpreter, if any */ 232 const char *interp; /* Pathname of the interpreter, if any */
233 Objlist dldags; /* Object belongs to these dlopened DAGs (%) */ 233 Objlist dldags; /* Object belongs to these dlopened DAGs (%) */
234 Objlist dagmembers; /* DAG has these members (%) */ 234 Objlist dagmembers; /* DAG has these members (%) */
235 dev_t dev; /* Object's filesystem's device */ 235 dev_t dev; /* Object's filesystem's device */
236 ino_t ino; /* Object's inode number */ 236 ino_t ino; /* Object's inode number */
237 237
238 void *ehdr; 238 void *ehdr;
239 239
240 /* SysV Hash fields */ 240 /* SysV Hash fields */
241 uint32_t nbuckets; /* Number of buckets */ 241 uint32_t nbuckets; /* Number of buckets */
242 uint32_t nbuckets_m; /* Precomputed for fast remainder */ 242 uint32_t nbuckets_m; /* Precomputed for fast remainder */
243 uint8_t nbuckets_s1; 243 uint8_t nbuckets_s1;
244 uint8_t nbuckets_s2; 244 uint8_t nbuckets_s2;
245 245
246 /* GNU Hash fields */ 246 /* GNU Hash fields */
247 const uint32_t *buckets_gnu; /* Hash table buckets array */ 247 const uint32_t *buckets_gnu; /* Hash table buckets array */
248 uint32_t nbuckets_gnu; /* Number of GNU hash buckets */ 248 uint32_t nbuckets_gnu; /* Number of GNU hash buckets */
249 uint32_t nbuckets_m_gnu; /* Precomputed for fast remainder */ 249 uint32_t nbuckets_m_gnu; /* Precomputed for fast remainder */
250 uint8_t nbuckets_s1_gnu; 250 uint8_t nbuckets_s1_gnu;
251 uint8_t nbuckets_s2_gnu; 251 uint8_t nbuckets_s2_gnu;
252 const uint32_t *chains_gnu; /* Hash table chain array */ 252 const uint32_t *chains_gnu; /* Hash table chain array */
253#define nchains_gnu nchains /* Number of symbols, shared with SysV Hash */ 253#define nchains_gnu nchains /* Number of symbols, shared with SysV Hash */
254 const Elf_Addr *bloom_gnu; 254 const Elf_Addr *bloom_gnu;
255 uint32_t symndx_gnu; /* First accessible symbol on dynsym table */ 255 uint32_t symndx_gnu; /* First accessible symbol on dynsym table */
256 uint32_t mask_bm_gnu; /* Bloom filter words - 1 (bitmask) */ 256 uint32_t mask_bm_gnu; /* Bloom filter words - 1 (bitmask) */
257 uint32_t shift2_gnu; /* Bloom filter shift count */ 257 uint32_t shift2_gnu; /* Bloom filter shift count */
258 258
259 size_t pathlen; /* Pathname length */ 259 size_t pathlen; /* Pathname length */
260 SIMPLEQ_HEAD(, Struct_Name_Entry) names; /* List of names for this 260 SIMPLEQ_HEAD(, Struct_Name_Entry) names; /* List of names for this
261 * object we know about. */ 261 * object we know about. */
262 262
263#ifdef __powerpc__ 263#ifdef __powerpc__
264#ifdef _LP64 264#ifdef _LP64
265 Elf_Addr glink; /* global linkage */ 265 Elf_Addr glink; /* global linkage */
266#else 266#else
267 Elf_Addr *gotptr; /* GOT table (secure-plt only) */ 267 Elf_Addr *gotptr; /* GOT table (secure-plt only) */
268#endif 268#endif
269#endif 269#endif
270 270
271#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) 271#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
272 /* Thread Local Storage support for this module */ 272 /* Thread Local Storage support for this module */
273 size_t tlsindex; /* Index in DTV */ 273 size_t tlsindex; /* Index in DTV */
274 void *tlsinit; /* Base address of TLS init block */ 274 void *tlsinit; /* Base address of TLS init block */
275 size_t tlsinitsize; /* Size of TLS init block */ 275 size_t tlsinitsize; /* Size of TLS init block */
276 size_t tlssize; /* Size of TLS block */ 276 size_t tlssize; /* Size of TLS block */
277 size_t tlsoffset; /* Offset in the static TLS block */ 277 size_t tlsoffset; /* Offset in the static TLS block */
278 size_t tlsalign; /* Needed alignment for static TLS */ 278 size_t tlsalign; /* Needed alignment for static TLS */
279#endif 279#endif
280 280
281#ifdef GNU_RELRO 281#ifdef GNU_RELRO
282 /* relocation readonly */ 282 /* relocation readonly */
283 void *relro_page; 283 void *relro_page;
284 size_t relro_size; 284 size_t relro_size;
285#endif 285#endif
286 286
287 /* symbol versioning */ 287 /* symbol versioning */
288 const Elf_Verneed *verneed; /* Required versions. */ 288 const Elf_Verneed *verneed; /* Required versions. */
289 Elf_Word verneednum; /* Number of entries in verneed table */ 289 Elf_Word verneednum; /* Number of entries in verneed table */
290 const Elf_Verdef *verdef; /* Provided versions. */ 290 const Elf_Verdef *verdef; /* Provided versions. */
291 Elf_Word verdefnum; /* Number of entries in verdef table */ 291 Elf_Word verdefnum; /* Number of entries in verdef table */
292 const Elf_Versym *versyms; /* Symbol versions table */ 292 const Elf_Versym *versyms; /* Symbol versions table */
293 293
294 Ver_Entry *vertab; /* Versions required/defined by this 294 Ver_Entry *vertab; /* Versions required/defined by this
295 * object */ 295 * object */
296 int vertabnum; /* Number of entries in vertab */ 296 int vertabnum; /* Number of entries in vertab */
297 297
298 /* init_array/fini_array */ 298 /* init_array/fini_array */
299 Elf_Addr *init_array; /* start of init array */ 299 Elf_Addr *init_array; /* start of init array */
300 size_t init_arraysz; /* # of entries in it */ 300 size_t init_arraysz; /* # of entries in it */
301 Elf_Addr *fini_array; /* start of fini array */ 301 Elf_Addr *fini_array; /* start of fini array */
302 size_t fini_arraysz; /* # of entries in it */ 302 size_t fini_arraysz; /* # of entries in it */
303 /* IRELATIVE relocations */ 303 /* IRELATIVE relocations */
304 size_t ifunc_remaining; 304 size_t ifunc_remaining;
305#if defined(__sparc__) || defined(__powerpc__) || defined(__arm__) || \ 305#if defined(__sparc__) || defined(__powerpc__) || defined(__arm__) || \
306 defined(__i386__) || defined(__x86_64__) 306 defined(__i386__) || defined(__x86_64__)
307#define IFUNC_NONPLT 307#define IFUNC_NONPLT
308 /* On SPARC, the PLT variant is called JMP_IREL and counted above. */ 308 /* On SPARC, the PLT variant is called JMP_IREL and counted above. */
309 size_t ifunc_remaining_nonplt; 309 size_t ifunc_remaining_nonplt;
310#endif 310#endif
311 size_t cxa_refcount; /* For TLS destructors. */ 311 size_t cxa_refcount; /* For TLS destructors. */
312#ifdef __ARM_EABI__ 312#ifdef __ARM_EABI__
313 void *exidx_start; 313 void *exidx_start;
314 size_t exidx_sz; 314 size_t exidx_sz;
315#endif 315#endif
316} Obj_Entry; 316} Obj_Entry;
317 317
318typedef struct Struct_DoneList { 318typedef struct Struct_DoneList {
319 const Obj_Entry **objs; /* Array of object pointers */ 319 const Obj_Entry **objs; /* Array of object pointers */
320 unsigned int num_alloc; /* Allocated size of the array */ 320 unsigned int num_alloc; /* Allocated size of the array */
321 unsigned int num_used; /* Number of array slots used */ 321 unsigned int num_used; /* Number of array slots used */
322} DoneList; 322} DoneList;
323 323
324 324
325#if defined(_RTLD_SOURCE) 325#if defined(_RTLD_SOURCE)
326 326
327extern struct r_debug _rtld_debug; 327extern struct r_debug _rtld_debug;
328extern Search_Path *_rtld_default_paths; 328extern Search_Path *_rtld_default_paths;
329extern Obj_Entry *_rtld_objlist; 329extern Obj_Entry *_rtld_objlist;
330extern Obj_Entry **_rtld_objtail; 330extern Obj_Entry **_rtld_objtail;
331extern u_int _rtld_objcount; 331extern u_int _rtld_objcount;
332extern u_int _rtld_objloads; 332extern u_int _rtld_objloads;
333extern const uintptr_t _rtld_compat_obj[]; 333extern const uintptr_t _rtld_compat_obj[];
334extern Obj_Entry *_rtld_objmain; 334extern Obj_Entry *_rtld_objmain;
335extern Obj_Entry _rtld_objself; 335extern Obj_Entry _rtld_objself;
336extern Search_Path *_rtld_paths; 336extern Search_Path *_rtld_paths;
337extern Library_Xform *_rtld_xforms; 337extern Library_Xform *_rtld_xforms;
338extern bool _rtld_trust; 338extern bool _rtld_trust;
339extern Objlist _rtld_list_global; 339extern Objlist _rtld_list_global;
340extern Objlist _rtld_list_main; 340extern Objlist _rtld_list_main;
341extern Elf_Sym _rtld_sym_zero; 341extern Elf_Sym _rtld_sym_zero;
342extern u_int _rtld_objgen; 342extern u_int _rtld_objgen;
343 343
344#define RTLD_MODEMASK 0x3 344#define RTLD_MODEMASK 0x3
345 345
346/* Flags to be passed into _rtld_symlook_ family of functions. */ 346/* Flags to be passed into _rtld_symlook_ family of functions. */
347#define SYMLOOK_IN_PLT 0x01 /* Lookup for PLT symbol */ 347#define SYMLOOK_IN_PLT 0x01 /* Lookup for PLT symbol */
348#define SYMLOOK_DLSYM 0x02 /* Return newest versioned symbol. 348#define SYMLOOK_DLSYM 0x02 /* Return newest versioned symbol.
349 Used by dlsym. */ 349 Used by dlsym. */
350 350
351/* Flags for _rtld_load_object() and friends. */ 351/* Flags for _rtld_load_object() and friends. */
352#define _RTLD_GLOBAL 0x01 /* Add object to global DAG. */ 352#define _RTLD_GLOBAL 0x01 /* Add object to global DAG. */
353#define _RTLD_MAIN 0x02 353#define _RTLD_MAIN 0x02
354#define _RTLD_NOLOAD 0x04 /* dlopen() specified RTLD_NOLOAD. */ 354#define _RTLD_NOLOAD 0x04 /* dlopen() specified RTLD_NOLOAD. */
355#define _RTLD_DLOPEN 0x08 /* Load_object() called from dlopen(). */ 355#define _RTLD_DLOPEN 0x08 /* Load_object() called from dlopen(). */
356 356
357/* Preallocation for static TLS model */ 357/* Preallocation for static TLS model */
358#define RTLD_STATIC_TLS_RESERVATION 64 358#define RTLD_STATIC_TLS_RESERVATION 64
359 359
360/* rtld.c */ 360/* rtld.c */
361__dso_public char *dlerror(void); 361__dso_public char *dlerror(void);
362__dso_public void *dlopen(const char *, int); 362__dso_public void *dlopen(const char *, int);
363__dso_public void *dlsym(void *, const char *); 363__dso_public void *dlsym(void *, const char *);
364__dso_public int dlclose(void *); 364__dso_public int dlclose(void *);
365__dso_public int dladdr(const void *, Dl_info *); 365__dso_public int dladdr(const void *, Dl_info *);
366__dso_public int dlinfo(void *, int, void *); 366__dso_public int dlinfo(void *, int, void *);
367__dso_public int dl_iterate_phdr(int (*)(struct dl_phdr_info *, size_t, void *), 367__dso_public int dl_iterate_phdr(int (*)(struct dl_phdr_info *, size_t, void *),
368 void *); 368 void *);
369 369
370__dso_public void *_dlauxinfo(void) __pure; 370__dso_public void *_dlauxinfo(void) __pure;
371__dso_public void __dl_cxa_refcount(void *addr, ssize_t delta); 371__dso_public void __dl_cxa_refcount(void *addr, ssize_t delta);
372 372
 373__dso_public pid_t __atomic_fork(void);
 374
373#if defined(__ARM_EABI__) && !defined(__ARM_DWARF_EH__) 375#if defined(__ARM_EABI__) && !defined(__ARM_DWARF_EH__)
374/* 376/*
375 * This is used by libgcc to find the start and length of the exception table 377 * This is used by libgcc to find the start and length of the exception table
376 * associated with a PC. 378 * associated with a PC.
377 */ 379 */
378__dso_public _Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr, int *); 380__dso_public _Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr, int *);
379#endif 381#endif
380 382
381/* These aren't exported */ 383/* These aren't exported */
382void _rtld_error(const char *, ...) __printflike(1,2); 384void _rtld_error(const char *, ...) __printflike(1,2);
383void _rtld_die(void) __dead; 385void _rtld_die(void) __dead;
384void *_rtld_objmain_sym(const char *); 386void *_rtld_objmain_sym(const char *);
385__dso_public void _rtld_debug_state(void) __noinline; 387__dso_public void _rtld_debug_state(void) __noinline;
386void _rtld_linkmap_add(Obj_Entry *); 388void _rtld_linkmap_add(Obj_Entry *);
387void _rtld_linkmap_delete(Obj_Entry *); 389void _rtld_linkmap_delete(Obj_Entry *);
388void _rtld_objlist_push_head(Objlist *, Obj_Entry *); 390void _rtld_objlist_push_head(Objlist *, Obj_Entry *);
389void _rtld_objlist_push_tail(Objlist *, Obj_Entry *); 391void _rtld_objlist_push_tail(Objlist *, Obj_Entry *);
390Objlist_Entry *_rtld_objlist_find(Objlist *, const Obj_Entry *); 392Objlist_Entry *_rtld_objlist_find(Objlist *, const Obj_Entry *);
391void _rtld_ref_dag(Obj_Entry *); 393void _rtld_ref_dag(Obj_Entry *);
392 394
393void _rtld_shared_enter(void); 395void _rtld_shared_enter(void);
394void _rtld_shared_exit(void); 396void _rtld_shared_exit(void);
395void _rtld_exclusive_enter(sigset_t *); 397void _rtld_exclusive_enter(sigset_t *);
396void _rtld_exclusive_exit(sigset_t *); 398void _rtld_exclusive_exit(sigset_t *);
397 399
398int _rtld_relro(const Obj_Entry *, bool); 400int _rtld_relro(const Obj_Entry *, bool);
399 401
400/* expand.c */ 402/* expand.c */
401size_t _rtld_expand_path(char *, size_t, const char *, const char *,\ 403size_t _rtld_expand_path(char *, size_t, const char *, const char *,\
402 const char *); 404 const char *);
403 405
404/* headers.c */ 406/* headers.c */
405void _rtld_digest_dynamic(const char *, Obj_Entry *); 407void _rtld_digest_dynamic(const char *, Obj_Entry *);
406Obj_Entry *_rtld_digest_phdr(const Elf_Phdr *, int, caddr_t); 408Obj_Entry *_rtld_digest_phdr(const Elf_Phdr *, int, caddr_t);
407 409
408/* load.c */ 410/* load.c */
409Obj_Entry *_rtld_load_object(const char *, int); 411Obj_Entry *_rtld_load_object(const char *, int);
410int _rtld_load_needed_objects(Obj_Entry *, int); 412int _rtld_load_needed_objects(Obj_Entry *, int);
411int _rtld_preload(const char *); 413int _rtld_preload(const char *);
412 414
413#define OBJ_ERR (Obj_Entry *)(-1) 415#define OBJ_ERR (Obj_Entry *)(-1)
414/* path.c */ 416/* path.c */
415void _rtld_add_paths(const char *, Search_Path **, const char *); 417void _rtld_add_paths(const char *, Search_Path **, const char *);
416void _rtld_process_hints(const char *, Search_Path **, Library_Xform **, 418void _rtld_process_hints(const char *, Search_Path **, Library_Xform **,
417 const char *); 419 const char *);
418int _rtld_sysctl(const char *, void *, size_t *); 420int _rtld_sysctl(const char *, void *, size_t *);
419 421
420/* reloc.c */ 422/* reloc.c */
421int _rtld_do_copy_relocations(const Obj_Entry *); 423int _rtld_do_copy_relocations(const Obj_Entry *);
422int _rtld_relocate_objects(Obj_Entry *, bool); 424int _rtld_relocate_objects(Obj_Entry *, bool);
423int _rtld_relocate_nonplt_objects(Obj_Entry *); 425int _rtld_relocate_nonplt_objects(Obj_Entry *);
424int _rtld_relocate_plt_lazy(Obj_Entry *); 426int _rtld_relocate_plt_lazy(Obj_Entry *);
425int _rtld_relocate_plt_objects(const Obj_Entry *); 427int _rtld_relocate_plt_objects(const Obj_Entry *);
426void _rtld_setup_pltgot(const Obj_Entry *); 428void _rtld_setup_pltgot(const Obj_Entry *);
427Elf_Addr _rtld_resolve_ifunc(const Obj_Entry *, const Elf_Sym *); 429Elf_Addr _rtld_resolve_ifunc(const Obj_Entry *, const Elf_Sym *);
428Elf_Addr _rtld_resolve_ifunc2(const Obj_Entry *, Elf_Addr); 430Elf_Addr _rtld_resolve_ifunc2(const Obj_Entry *, Elf_Addr);
429 431
430void _rtld_call_ifunc(Obj_Entry *, sigset_t *, u_int); 432void _rtld_call_ifunc(Obj_Entry *, sigset_t *, u_int);
431 433
432/* search.c */ 434/* search.c */
433Obj_Entry *_rtld_load_library(const char *, const Obj_Entry *, int); 435Obj_Entry *_rtld_load_library(const char *, const Obj_Entry *, int);
434 436
435/* symbol.c */ 437/* symbol.c */
436unsigned long _rtld_sysv_hash(const char *); 438unsigned long _rtld_sysv_hash(const char *);
437unsigned long _rtld_gnu_hash(const char *); 439unsigned long _rtld_gnu_hash(const char *);
438const Elf_Sym *_rtld_symlook_obj(const char *, Elf_Hash *, 440const Elf_Sym *_rtld_symlook_obj(const char *, Elf_Hash *,
439 const Obj_Entry *, u_int, const Ver_Entry *); 441 const Obj_Entry *, u_int, const Ver_Entry *);
440const Elf_Sym *_rtld_find_symdef(unsigned long, const Obj_Entry *, 442const Elf_Sym *_rtld_find_symdef(unsigned long, const Obj_Entry *,
441 const Obj_Entry **, u_int); 443 const Obj_Entry **, u_int);
442const Elf_Sym *_rtld_find_plt_symdef(unsigned long, const Obj_Entry *, 444const Elf_Sym *_rtld_find_plt_symdef(unsigned long, const Obj_Entry *,
443 const Obj_Entry **, bool); 445 const Obj_Entry **, bool);
444 446
445const Elf_Sym *_rtld_symlook_list(const char *, Elf_Hash *, 447const Elf_Sym *_rtld_symlook_list(const char *, Elf_Hash *,
446 const Objlist *, const Obj_Entry **, u_int, const Ver_Entry *, DoneList *); 448 const Objlist *, const Obj_Entry **, u_int, const Ver_Entry *, DoneList *);
447const Elf_Sym *_rtld_symlook_default(const char *, Elf_Hash *, 449const Elf_Sym *_rtld_symlook_default(const char *, Elf_Hash *,
448 const Obj_Entry *, const Obj_Entry **, u_int, const Ver_Entry *); 450 const Obj_Entry *, const Obj_Entry **, u_int, const Ver_Entry *);
449const Elf_Sym *_rtld_symlook_needed(const char *, Elf_Hash *, 451const Elf_Sym *_rtld_symlook_needed(const char *, Elf_Hash *,
450 const Needed_Entry *, const Obj_Entry **, u_int, const Ver_Entry *, 452 const Needed_Entry *, const Obj_Entry **, u_int, const Ver_Entry *,
451 DoneList *, DoneList *); 453 DoneList *, DoneList *);
452 454
453/* symver.c */ 455/* symver.c */
454void _rtld_object_add_name(Obj_Entry *, const char *); 456void _rtld_object_add_name(Obj_Entry *, const char *);
455int _rtld_object_match_name(const Obj_Entry *, const char *); 457int _rtld_object_match_name(const Obj_Entry *, const char *);
456int _rtld_verify_object_versions(Obj_Entry *); 458int _rtld_verify_object_versions(Obj_Entry *);
457 459
458static __inline const Ver_Entry * 460static __inline const Ver_Entry *
459_rtld_fetch_ventry(const Obj_Entry *obj, unsigned long symnum) 461_rtld_fetch_ventry(const Obj_Entry *obj, unsigned long symnum)
460{ 462{
461 Elf_Half vernum; 463 Elf_Half vernum;
462 464
463 if (obj->vertab) { 465 if (obj->vertab) {
464 vernum = VER_NDX(obj->versyms[symnum].vs_vers); 466 vernum = VER_NDX(obj->versyms[symnum].vs_vers);
465 if (vernum >= obj->vertabnum) { 467 if (vernum >= obj->vertabnum) {
466 _rtld_error("%s: symbol %s has wrong verneed value %d", 468 _rtld_error("%s: symbol %s has wrong verneed value %d",
467 obj->path, &obj->strtab[symnum], vernum); 469 obj->path, &obj->strtab[symnum], vernum);
468 } else if (obj->vertab[vernum].hash) { 470 } else if (obj->vertab[vernum].hash) {
469 return &obj->vertab[vernum]; 471 return &obj->vertab[vernum];
470 } 472 }
471 } 473 }
472 return NULL; 474 return NULL;
473} 475}
474 476
475#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) 477#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
476/* tls.c */ 478/* tls.c */
477void *_rtld_tls_get_addr(void *, size_t, size_t); 479void *_rtld_tls_get_addr(void *, size_t, size_t);
478void _rtld_tls_initial_allocation(void); 480void _rtld_tls_initial_allocation(void);
479void *_rtld_tls_module_allocate(size_t index); 481void *_rtld_tls_module_allocate(size_t index);
480int _rtld_tls_offset_allocate(Obj_Entry *); 482int _rtld_tls_offset_allocate(Obj_Entry *);
481void _rtld_tls_offset_free(Obj_Entry *); 483void _rtld_tls_offset_free(Obj_Entry *);
482 484
483extern size_t _rtld_tls_dtv_generation; 485extern size_t _rtld_tls_dtv_generation;
484extern size_t _rtld_tls_max_index; 486extern size_t _rtld_tls_max_index;
485 487
486__dso_public extern void *__tls_get_addr(void *); 488__dso_public extern void *__tls_get_addr(void *);
487#ifdef __i386__ 489#ifdef __i386__
488__dso_public extern void *___tls_get_addr(void *) 490__dso_public extern void *___tls_get_addr(void *)
489 __attribute__((__regparm__(1))); 491 __attribute__((__regparm__(1)));
490#endif 492#endif
491#endif 493#endif
492 494
493/* map_object.c */ 495/* map_object.c */
494struct stat; 496struct stat;
495Obj_Entry *_rtld_map_object(const char *, int, const struct stat *); 497Obj_Entry *_rtld_map_object(const char *, int, const struct stat *);
496void _rtld_obj_free(Obj_Entry *); 498void _rtld_obj_free(Obj_Entry *);
497Obj_Entry *_rtld_obj_new(void); 499Obj_Entry *_rtld_obj_new(void);
498 500
499#ifdef RTLD_LOADER 501#ifdef RTLD_LOADER
500/* function descriptors */ 502/* function descriptors */
501#ifdef __HAVE_FUNCTION_DESCRIPTORS 503#ifdef __HAVE_FUNCTION_DESCRIPTORS
502Elf_Addr _rtld_function_descriptor_alloc(const Obj_Entry *, 504Elf_Addr _rtld_function_descriptor_alloc(const Obj_Entry *,
503 const Elf_Sym *, Elf_Addr); 505 const Elf_Sym *, Elf_Addr);
504const void *_rtld_function_descriptor_function(const void *); 506const void *_rtld_function_descriptor_function(const void *);
505 507
506void _rtld_call_function_void(const Obj_Entry *, Elf_Addr); 508void _rtld_call_function_void(const Obj_Entry *, Elf_Addr);
507Elf_Addr _rtld_call_function_addr(const Obj_Entry *, Elf_Addr); 509Elf_Addr _rtld_call_function_addr(const Obj_Entry *, Elf_Addr);
508#else 510#else
509static inline void 511static inline void
510_rtld_call_function_void(const Obj_Entry *obj, Elf_Addr addr) 512_rtld_call_function_void(const Obj_Entry *obj, Elf_Addr addr)
511{ 513{
512 ((void (*)(void))addr)(); 514 ((void (*)(void))addr)();
513} 515}
514static inline Elf_Addr 516static inline Elf_Addr
515_rtld_call_function_addr(const Obj_Entry *obj, Elf_Addr addr) 517_rtld_call_function_addr(const Obj_Entry *obj, Elf_Addr addr)
516{ 518{
517 return ((Elf_Addr(*)(void))addr)(); 519 return ((Elf_Addr(*)(void))addr)();
518} 520}
519#endif /* __HAVE_FUNCTION_DESCRIPTORS */ 521#endif /* __HAVE_FUNCTION_DESCRIPTORS */
520#endif /* RTLD_LOADER */ 522#endif /* RTLD_LOADER */
521 523
522#endif /* _RTLD_SOURCE */ 524#endif /* _RTLD_SOURCE */
523 525
524#endif /* RTLD_H */ 526#endif /* RTLD_H */

cvs diff -r1.2 -r1.3 src/libexec/ld.elf_so/symbols.map (switch to unified diff)

--- src/libexec/ld.elf_so/symbols.map 2017/07/11 15:21:35 1.2
+++ src/libexec/ld.elf_so/symbols.map 2020/04/16 14:39:58 1.3
@@ -1,27 +1,28 @@ @@ -1,27 +1,28 @@
1{ 1{
2 global: 2 global:
3 dlopen; 3 dlopen;
4 __dlopen; 4 __dlopen;
5 dlclose; 5 dlclose;
6 __dlclose; 6 __dlclose;
7 dlsym; 7 dlsym;
8 __dlsym; 8 __dlsym;
9 dlvsym; 9 dlvsym;
10 __dlvsym; 10 __dlvsym;
11 dlerror; 11 dlerror;
12 __dlerror; 12 __dlerror;
13 dladdr; 13 dladdr;
14 __dladdr; 14 __dladdr;
15 dlinfo; 15 dlinfo;
16 __dlinfo; 16 __dlinfo;
17 dl_iterate_phdr; 17 dl_iterate_phdr;
18 ____dl_iterate_phdr; 18 ____dl_iterate_phdr;
19 _dlauxinfo; 19 _dlauxinfo;
20 _rtld_tls_allocate; 20 _rtld_tls_allocate;
21 _rtld_tls_free; 21 _rtld_tls_free;
22 __tls_get_addr; 22 __tls_get_addr;
23 ___tls_get_addr; 23 ___tls_get_addr;
24 __gnu_Unwind_Find_exidx; 24 __gnu_Unwind_Find_exidx;
25 __dl_cxa_refcount; 25 __dl_cxa_refcount;
 26 __atomic_fork;
26 local: *; 27 local: *;
27}; 28};