Sun May 30 02:26:08 2021 UTC ()
Don't use the return address hack with clang.


(joerg)
diff -r1.207 -r1.208 src/libexec/ld.elf_so/rtld.c

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

--- src/libexec/ld.elf_so/rtld.c 2020/09/22 00:41:27 1.207
+++ src/libexec/ld.elf_so/rtld.c 2021/05/30 02:26:08 1.208
@@ -1,1820 +1,1820 @@ @@ -1,1820 +1,1820 @@
1/* $NetBSD: rtld.c,v 1.207 2020/09/22 00:41:27 kamil Exp $ */ 1/* $NetBSD: rtld.c,v 1.208 2021/05/30 02:26:08 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.207 2020/09/22 00:41:27 kamil Exp $"); 43__RCSID("$NetBSD: rtld.c,v 1.208 2021/05/30 02:26:08 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; /* The SVR4 interface for the debugger */ 84struct r_debug _rtld_debug; /* The SVR4 interface for the debugger */
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_version = R_DEBUG_VERSION; 397 _rtld_debug.r_version = R_DEBUG_VERSION;
398 _rtld_debug.r_brk = _rtld_debug_state; 398 _rtld_debug.r_brk = _rtld_debug_state;
399 _rtld_debug.r_state = RT_CONSISTENT; 399 _rtld_debug.r_state = RT_CONSISTENT;
400 _rtld_debug.r_ldbase = _rtld_objself.relocbase; 400 _rtld_debug.r_ldbase = _rtld_objself.relocbase;
401 401
402 ehdr = (Elf_Ehdr *)mapbase; 402 ehdr = (Elf_Ehdr *)mapbase;
403 _rtld_objself.phdr = (Elf_Phdr *)((char *)mapbase + ehdr->e_phoff); 403 _rtld_objself.phdr = (Elf_Phdr *)((char *)mapbase + ehdr->e_phoff);
404 _rtld_objself.phsize = ehdr->e_phnum * sizeof(_rtld_objself.phdr[0]); 404 _rtld_objself.phsize = ehdr->e_phnum * sizeof(_rtld_objself.phdr[0]);
405} 405}
406 406
407/* 407/*
408 * Cleanup procedure. It will be called (by the atexit() mechanism) just 408 * Cleanup procedure. It will be called (by the atexit() mechanism) just
409 * before the process exits. 409 * before the process exits.
410 */ 410 */
411static void 411static void
412_rtld_exit(void) 412_rtld_exit(void)
413{ 413{
414 sigset_t mask; 414 sigset_t mask;
415 415
416 dbg(("rtld_exit()")); 416 dbg(("rtld_exit()"));
417 417
418 _rtld_exclusive_enter(&mask); 418 _rtld_exclusive_enter(&mask);
419 419
420 _rtld_call_fini_functions(&mask, 1); 420 _rtld_call_fini_functions(&mask, 1);
421 421
422 _rtld_exclusive_exit(&mask); 422 _rtld_exclusive_exit(&mask);
423} 423}
424 424
425__dso_public void * 425__dso_public void *
426_dlauxinfo(void) 426_dlauxinfo(void)
427{ 427{
428 return auxinfo; 428 return auxinfo;
429} 429}
430 430
431/* 431/*
432 * Main entry point for dynamic linking. The argument is the stack 432 * Main entry point for dynamic linking. The argument is the stack
433 * pointer. The stack is expected to be laid out as described in the 433 * pointer. The stack is expected to be laid out as described in the
434 * SVR4 ABI specification, Intel 386 Processor Supplement. Specifically, 434 * SVR4 ABI specification, Intel 386 Processor Supplement. Specifically,
435 * the stack pointer points to a word containing ARGC. Following that 435 * the stack pointer points to a word containing ARGC. Following that
436 * in the stack is a null-terminated sequence of pointers to argument 436 * in the stack is a null-terminated sequence of pointers to argument
437 * strings. Then comes a null-terminated sequence of pointers to 437 * strings. Then comes a null-terminated sequence of pointers to
438 * environment strings. Finally, there is a sequence of "auxiliary 438 * environment strings. Finally, there is a sequence of "auxiliary
439 * vector" entries. 439 * vector" entries.
440 * 440 *
441 * This function returns the entry point for the main program, the dynamic 441 * This function returns the entry point for the main program, the dynamic
442 * linker's exit procedure in sp[0], and a pointer to the main object in 442 * linker's exit procedure in sp[0], and a pointer to the main object in
443 * sp[1]. 443 * sp[1].
444 */ 444 */
445Elf_Addr 445Elf_Addr
446_rtld(Elf_Addr *sp, Elf_Addr relocbase) 446_rtld(Elf_Addr *sp, Elf_Addr relocbase)
447{ 447{
448 const AuxInfo *pAUX_base, *pAUX_entry, *pAUX_execfd, *pAUX_phdr, 448 const AuxInfo *pAUX_base, *pAUX_entry, *pAUX_execfd, *pAUX_phdr,
449 *pAUX_phent, *pAUX_phnum, *pAUX_euid, *pAUX_egid, 449 *pAUX_phent, *pAUX_phnum, *pAUX_euid, *pAUX_egid,
450 *pAUX_ruid, *pAUX_rgid; 450 *pAUX_ruid, *pAUX_rgid;
451 const AuxInfo *pAUX_pagesz; 451 const AuxInfo *pAUX_pagesz;
452 char **env, **oenvp; 452 char **env, **oenvp;
453 const AuxInfo *auxp; 453 const AuxInfo *auxp;
454 Obj_Entry *obj; 454 Obj_Entry *obj;
455 Elf_Addr *const osp = sp; 455 Elf_Addr *const osp = sp;
456 bool bind_now = 0; 456 bool bind_now = 0;
457 const char *ld_bind_now, *ld_preload, *ld_library_path; 457 const char *ld_bind_now, *ld_preload, *ld_library_path;
458 const char **argv; 458 const char **argv;
459 const char *execname; 459 const char *execname;
460 long argc; 460 long argc;
461 const char **real___progname; 461 const char **real___progname;
462 const Obj_Entry **real___mainprog_obj; 462 const Obj_Entry **real___mainprog_obj;
463 char ***real_environ; 463 char ***real_environ;
464 sigset_t mask; 464 sigset_t mask;
465#ifdef DEBUG 465#ifdef DEBUG
466 const char *ld_debug; 466 const char *ld_debug;
467#endif 467#endif
468#ifdef RTLD_DEBUG 468#ifdef RTLD_DEBUG
469 int i = 0; 469 int i = 0;
470#endif 470#endif
471 471
472 /* 472 /*
473 * On entry, the dynamic linker itself has not been relocated yet. 473 * On entry, the dynamic linker itself has not been relocated yet.
474 * Be very careful not to reference any global data until after 474 * Be very careful not to reference any global data until after
475 * _rtld_init has returned. It is OK to reference file-scope statics 475 * _rtld_init has returned. It is OK to reference file-scope statics
476 * and string constants, and to call static and global functions. 476 * and string constants, and to call static and global functions.
477 */ 477 */
478 /* Find the auxiliary vector on the stack. */ 478 /* Find the auxiliary vector on the stack. */
479 /* first Elf_Word reserved to address of exit routine */ 479 /* first Elf_Word reserved to address of exit routine */
480#if defined(RTLD_DEBUG) 480#if defined(RTLD_DEBUG)
481 debug = 1; 481 debug = 1;
482 dbg(("sp = %p, argc = %ld, argv = %p <%s> relocbase %p", sp, 482 dbg(("sp = %p, argc = %ld, argv = %p <%s> relocbase %p", sp,
483 (long)sp[2], &sp[3], (char *) sp[3], (void *)relocbase)); 483 (long)sp[2], &sp[3], (char *) sp[3], (void *)relocbase));
484#ifndef __x86_64__ 484#ifndef __x86_64__
485 dbg(("got is at %p, dynamic is at %p", _GLOBAL_OFFSET_TABLE_, 485 dbg(("got is at %p, dynamic is at %p", _GLOBAL_OFFSET_TABLE_,
486 &_DYNAMIC)); 486 &_DYNAMIC));
487#endif 487#endif
488#endif 488#endif
489 489
490 sp += 2; /* skip over return argument space */ 490 sp += 2; /* skip over return argument space */
491 argv = (const char **) &sp[1]; 491 argv = (const char **) &sp[1];
492 argc = *(long *)sp; 492 argc = *(long *)sp;
493 sp += 2 + argc; /* Skip over argc, arguments, and NULL 493 sp += 2 + argc; /* Skip over argc, arguments, and NULL
494 * terminator */ 494 * terminator */
495 env = (char **) sp; 495 env = (char **) sp;
496 while (*sp++ != 0) { /* Skip over environment, and NULL terminator */ 496 while (*sp++ != 0) { /* Skip over environment, and NULL terminator */
497#if defined(RTLD_DEBUG) 497#if defined(RTLD_DEBUG)
498 dbg(("env[%d] = %p %s", i++, (void *)sp[-1], (char *)sp[-1])); 498 dbg(("env[%d] = %p %s", i++, (void *)sp[-1], (char *)sp[-1]));
499#endif 499#endif
500 } 500 }
501 auxinfo = (AuxInfo *) sp; 501 auxinfo = (AuxInfo *) sp;
502 502
503 pAUX_base = pAUX_entry = pAUX_execfd = NULL; 503 pAUX_base = pAUX_entry = pAUX_execfd = NULL;
504 pAUX_phdr = pAUX_phent = pAUX_phnum = NULL; 504 pAUX_phdr = pAUX_phent = pAUX_phnum = NULL;
505 pAUX_euid = pAUX_ruid = pAUX_egid = pAUX_rgid = NULL; 505 pAUX_euid = pAUX_ruid = pAUX_egid = pAUX_rgid = NULL;
506 pAUX_pagesz = NULL; 506 pAUX_pagesz = NULL;
507 507
508 execname = NULL; 508 execname = NULL;
509 509
510 /* Digest the auxiliary vector. */ 510 /* Digest the auxiliary vector. */
511 for (auxp = auxinfo; auxp->a_type != AT_NULL; ++auxp) { 511 for (auxp = auxinfo; auxp->a_type != AT_NULL; ++auxp) {
512 switch (auxp->a_type) { 512 switch (auxp->a_type) {
513 case AT_BASE: 513 case AT_BASE:
514 pAUX_base = auxp; 514 pAUX_base = auxp;
515 break; 515 break;
516 case AT_ENTRY: 516 case AT_ENTRY:
517 pAUX_entry = auxp; 517 pAUX_entry = auxp;
518 break; 518 break;
519 case AT_EXECFD: 519 case AT_EXECFD:
520 pAUX_execfd = auxp; 520 pAUX_execfd = auxp;
521 break; 521 break;
522 case AT_PHDR: 522 case AT_PHDR:
523 pAUX_phdr = auxp; 523 pAUX_phdr = auxp;
524 break; 524 break;
525 case AT_PHENT: 525 case AT_PHENT:
526 pAUX_phent = auxp; 526 pAUX_phent = auxp;
527 break; 527 break;
528 case AT_PHNUM: 528 case AT_PHNUM:
529 pAUX_phnum = auxp; 529 pAUX_phnum = auxp;
530 break; 530 break;
531#ifdef AT_EUID 531#ifdef AT_EUID
532 case AT_EUID: 532 case AT_EUID:
533 pAUX_euid = auxp; 533 pAUX_euid = auxp;
534 break; 534 break;
535 case AT_RUID: 535 case AT_RUID:
536 pAUX_ruid = auxp; 536 pAUX_ruid = auxp;
537 break; 537 break;
538 case AT_EGID: 538 case AT_EGID:
539 pAUX_egid = auxp; 539 pAUX_egid = auxp;
540 break; 540 break;
541 case AT_RGID: 541 case AT_RGID:
542 pAUX_rgid = auxp; 542 pAUX_rgid = auxp;
543 break; 543 break;
544#endif 544#endif
545#ifdef AT_SUN_EXECNAME 545#ifdef AT_SUN_EXECNAME
546 case AT_SUN_EXECNAME: 546 case AT_SUN_EXECNAME:
547 execname = (const char *)(const void *)auxp->a_v; 547 execname = (const char *)(const void *)auxp->a_v;
548 break; 548 break;
549#endif 549#endif
550 case AT_PAGESZ: 550 case AT_PAGESZ:
551 pAUX_pagesz = auxp; 551 pAUX_pagesz = auxp;
552 break; 552 break;
553 } 553 }
554 } 554 }
555 555
556 /* Initialize and relocate ourselves. */ 556 /* Initialize and relocate ourselves. */
557 if (pAUX_base == NULL) { 557 if (pAUX_base == NULL) {
558 _rtld_error("Bad pAUX_base"); 558 _rtld_error("Bad pAUX_base");
559 _rtld_die(); 559 _rtld_die();
560 } 560 }
561 assert(pAUX_pagesz != NULL); 561 assert(pAUX_pagesz != NULL);
562 _rtld_pagesz = (int)pAUX_pagesz->a_v; 562 _rtld_pagesz = (int)pAUX_pagesz->a_v;
563 _rtld_init((caddr_t)pAUX_base->a_v, (caddr_t)relocbase, execname); 563 _rtld_init((caddr_t)pAUX_base->a_v, (caddr_t)relocbase, execname);
564 564
565 __progname = _rtld_objself.path; 565 __progname = _rtld_objself.path;
566 environ = env; 566 environ = env;
567 567
568 _rtld_trust = ((pAUX_euid ? (uid_t)pAUX_euid->a_v : geteuid()) == 568 _rtld_trust = ((pAUX_euid ? (uid_t)pAUX_euid->a_v : geteuid()) ==
569 (pAUX_ruid ? (uid_t)pAUX_ruid->a_v : getuid())) && 569 (pAUX_ruid ? (uid_t)pAUX_ruid->a_v : getuid())) &&
570 ((pAUX_egid ? (gid_t)pAUX_egid->a_v : getegid()) == 570 ((pAUX_egid ? (gid_t)pAUX_egid->a_v : getegid()) ==
571 (pAUX_rgid ? (gid_t)pAUX_rgid->a_v : getgid())); 571 (pAUX_rgid ? (gid_t)pAUX_rgid->a_v : getgid()));
572 572
573#ifdef DEBUG 573#ifdef DEBUG
574 ld_debug = NULL; 574 ld_debug = NULL;
575#endif 575#endif
576 ld_bind_now = NULL; 576 ld_bind_now = NULL;
577 ld_library_path = NULL; 577 ld_library_path = NULL;
578 ld_preload = NULL; 578 ld_preload = NULL;
579 /* 579 /*
580 * Inline avoid using normal getenv/unsetenv here as the libc 580 * Inline avoid using normal getenv/unsetenv here as the libc
581 * code is quite a bit more complicated. 581 * code is quite a bit more complicated.
582 */ 582 */
583 for (oenvp = env; *env != NULL; ++env) { 583 for (oenvp = env; *env != NULL; ++env) {
584 static const char bind_var[] = "LD_BIND_NOW="; 584 static const char bind_var[] = "LD_BIND_NOW=";
585 static const char debug_var[] = "LD_DEBUG="; 585 static const char debug_var[] = "LD_DEBUG=";
586 static const char path_var[] = "LD_LIBRARY_PATH="; 586 static const char path_var[] = "LD_LIBRARY_PATH=";
587 static const char preload_var[] = "LD_PRELOAD="; 587 static const char preload_var[] = "LD_PRELOAD=";
588#define LEN(x) (sizeof(x) - 1) 588#define LEN(x) (sizeof(x) - 1)
589 589
590 if ((*env)[0] != 'L' || (*env)[1] != 'D') { 590 if ((*env)[0] != 'L' || (*env)[1] != 'D') {
591 /* 591 /*
592 * Special case to skip most entries without 592 * Special case to skip most entries without
593 * the more expensive calls to strncmp. 593 * the more expensive calls to strncmp.
594 */ 594 */
595 *oenvp++ = *env; 595 *oenvp++ = *env;
596 } else if (strncmp(*env, debug_var, LEN(debug_var)) == 0) { 596 } else if (strncmp(*env, debug_var, LEN(debug_var)) == 0) {
597 if (_rtld_trust) { 597 if (_rtld_trust) {
598#ifdef DEBUG 598#ifdef DEBUG
599 ld_debug = *env + LEN(debug_var); 599 ld_debug = *env + LEN(debug_var);
600#endif 600#endif
601 *oenvp++ = *env; 601 *oenvp++ = *env;
602 } 602 }
603 } else if (strncmp(*env, bind_var, LEN(bind_var)) == 0) { 603 } else if (strncmp(*env, bind_var, LEN(bind_var)) == 0) {
604 if (_rtld_trust) { 604 if (_rtld_trust) {
605 ld_bind_now = *env + LEN(bind_var); 605 ld_bind_now = *env + LEN(bind_var);
606 *oenvp++ = *env; 606 *oenvp++ = *env;
607 } 607 }
608 } else if (strncmp(*env, path_var, LEN(path_var)) == 0) { 608 } else if (strncmp(*env, path_var, LEN(path_var)) == 0) {
609 if (_rtld_trust) { 609 if (_rtld_trust) {
610 ld_library_path = *env + LEN(path_var); 610 ld_library_path = *env + LEN(path_var);
611 *oenvp++ = *env; 611 *oenvp++ = *env;
612 } 612 }
613 } else if (strncmp(*env, preload_var, LEN(preload_var)) == 0) { 613 } else if (strncmp(*env, preload_var, LEN(preload_var)) == 0) {
614 if (_rtld_trust) { 614 if (_rtld_trust) {
615 ld_preload = *env + LEN(preload_var); 615 ld_preload = *env + LEN(preload_var);
616 *oenvp++ = *env; 616 *oenvp++ = *env;
617 } 617 }
618 } else { 618 } else {
619 *oenvp++ = *env; 619 *oenvp++ = *env;
620 } 620 }
621#undef LEN 621#undef LEN
622 } 622 }
623 *oenvp++ = NULL; 623 *oenvp++ = NULL;
624 624
625 if (ld_bind_now != NULL && *ld_bind_now != '\0') 625 if (ld_bind_now != NULL && *ld_bind_now != '\0')
626 bind_now = true; 626 bind_now = true;
627 if (_rtld_trust) { 627 if (_rtld_trust) {
628#ifdef DEBUG 628#ifdef DEBUG
629#ifdef RTLD_DEBUG 629#ifdef RTLD_DEBUG
630 debug = 0; 630 debug = 0;
631#endif 631#endif
632 if (ld_debug != NULL && *ld_debug != '\0') 632 if (ld_debug != NULL && *ld_debug != '\0')
633 debug = 1; 633 debug = 1;
634#endif 634#endif
635 _rtld_add_paths(execname, &_rtld_paths, ld_library_path); 635 _rtld_add_paths(execname, &_rtld_paths, ld_library_path);
636 } else { 636 } else {
637 execname = NULL; 637 execname = NULL;
638 } 638 }
639 _rtld_process_hints(execname, &_rtld_paths, &_rtld_xforms, 639 _rtld_process_hints(execname, &_rtld_paths, &_rtld_xforms,
640 _PATH_LD_HINTS); 640 _PATH_LD_HINTS);
641 dbg(("dynamic linker is initialized, mapbase=%p, relocbase=%p", 641 dbg(("dynamic linker is initialized, mapbase=%p, relocbase=%p",
642 _rtld_objself.mapbase, _rtld_objself.relocbase)); 642 _rtld_objself.mapbase, _rtld_objself.relocbase));
643 643
644 /* 644 /*
645 * Load the main program, or process its program header if it is 645 * Load the main program, or process its program header if it is
646 * already loaded. 646 * already loaded.
647 */ 647 */
648 if (pAUX_execfd != NULL) { /* Load the main program. */ 648 if (pAUX_execfd != NULL) { /* Load the main program. */
649 int fd = pAUX_execfd->a_v; 649 int fd = pAUX_execfd->a_v;
650 const char *obj_name = argv[0] ? argv[0] : "main program"; 650 const char *obj_name = argv[0] ? argv[0] : "main program";
651 dbg(("loading main program")); 651 dbg(("loading main program"));
652 _rtld_objmain = _rtld_map_object(obj_name, fd, NULL); 652 _rtld_objmain = _rtld_map_object(obj_name, fd, NULL);
653 close(fd); 653 close(fd);
654 if (_rtld_objmain == NULL) 654 if (_rtld_objmain == NULL)
655 _rtld_die(); 655 _rtld_die();
656 } else { /* Main program already loaded. */ 656 } else { /* Main program already loaded. */
657 const Elf_Phdr *phdr; 657 const Elf_Phdr *phdr;
658 int phnum; 658 int phnum;
659 caddr_t entry; 659 caddr_t entry;
660 660
661 dbg(("processing main program's program header")); 661 dbg(("processing main program's program header"));
662 assert(pAUX_phdr != NULL); 662 assert(pAUX_phdr != NULL);
663 phdr = (const Elf_Phdr *) pAUX_phdr->a_v; 663 phdr = (const Elf_Phdr *) pAUX_phdr->a_v;
664 assert(pAUX_phnum != NULL); 664 assert(pAUX_phnum != NULL);
665 phnum = pAUX_phnum->a_v; 665 phnum = pAUX_phnum->a_v;
666 assert(pAUX_phent != NULL); 666 assert(pAUX_phent != NULL);
667 assert(pAUX_phent->a_v == sizeof(Elf_Phdr)); 667 assert(pAUX_phent->a_v == sizeof(Elf_Phdr));
668 assert(pAUX_entry != NULL); 668 assert(pAUX_entry != NULL);
669 entry = (caddr_t) pAUX_entry->a_v; 669 entry = (caddr_t) pAUX_entry->a_v;
670 _rtld_objmain = _rtld_digest_phdr(phdr, phnum, entry); 670 _rtld_objmain = _rtld_digest_phdr(phdr, phnum, entry);
671 _rtld_objmain->path = xstrdup(argv[0] ? argv[0] : 671 _rtld_objmain->path = xstrdup(argv[0] ? argv[0] :
672 "main program"); 672 "main program");
673 _rtld_objmain->pathlen = strlen(_rtld_objmain->path); 673 _rtld_objmain->pathlen = strlen(_rtld_objmain->path);
674 } 674 }
675 675
676 _rtld_objmain->mainprog = true; 676 _rtld_objmain->mainprog = true;
677 677
678 /* 678 /*
679 * Get the actual dynamic linker pathname from the executable if 679 * Get the actual dynamic linker pathname from the executable if
680 * possible. (It should always be possible.) That ensures that 680 * possible. (It should always be possible.) That ensures that
681 * the debugger will find the right dynamic linker even if a 681 * the debugger will find the right dynamic linker even if a
682 * non-standard one is being used. 682 * non-standard one is being used.
683 */ 683 */
684 if (_rtld_objmain->interp != NULL && 684 if (_rtld_objmain->interp != NULL &&
685 strcmp(_rtld_objmain->interp, _rtld_objself.path) != 0) { 685 strcmp(_rtld_objmain->interp, _rtld_objself.path) != 0) {
686 _rtld_objself.path = xstrdup(_rtld_objmain->interp); 686 _rtld_objself.path = xstrdup(_rtld_objmain->interp);
687 _rtld_objself.pathlen = strlen(_rtld_objself.path); 687 _rtld_objself.pathlen = strlen(_rtld_objself.path);
688 } 688 }
689 dbg(("actual dynamic linker is %s", _rtld_objself.path)); 689 dbg(("actual dynamic linker is %s", _rtld_objself.path));
690 690
691 _rtld_digest_dynamic(execname, _rtld_objmain); 691 _rtld_digest_dynamic(execname, _rtld_objmain);
692 692
693 /* Link the main program into the list of objects. */ 693 /* Link the main program into the list of objects. */
694 *_rtld_objtail = _rtld_objmain; 694 *_rtld_objtail = _rtld_objmain;
695 _rtld_objtail = &_rtld_objmain->next; 695 _rtld_objtail = &_rtld_objmain->next;
696 _rtld_objcount++; 696 _rtld_objcount++;
697 _rtld_objloads++; 697 _rtld_objloads++;
698 698
699 _rtld_linkmap_add(_rtld_objmain); 699 _rtld_linkmap_add(_rtld_objmain);
700 _rtld_objself.path = xstrdup(_rtld_objself.path); 700 _rtld_objself.path = xstrdup(_rtld_objself.path);
701 _rtld_linkmap_add(&_rtld_objself); 701 _rtld_linkmap_add(&_rtld_objself);
702 702
703 ++_rtld_objmain->refcount; 703 ++_rtld_objmain->refcount;
704 _rtld_objmain->mainref = 1; 704 _rtld_objmain->mainref = 1;
705 _rtld_objlist_push_tail(&_rtld_list_main, _rtld_objmain); 705 _rtld_objlist_push_tail(&_rtld_list_main, _rtld_objmain);
706 706
707 if (ld_preload) { 707 if (ld_preload) {
708 /* 708 /*
709 * Pre-load user-specified objects after the main program 709 * Pre-load user-specified objects after the main program
710 * but before any shared object dependencies. 710 * but before any shared object dependencies.
711 */ 711 */
712 dbg(("preloading objects")); 712 dbg(("preloading objects"));
713 if (_rtld_preload(ld_preload) == -1) 713 if (_rtld_preload(ld_preload) == -1)
714 _rtld_die(); 714 _rtld_die();
715 } 715 }
716 716
717 dbg(("loading needed objects")); 717 dbg(("loading needed objects"));
718 if (_rtld_load_needed_objects(_rtld_objmain, _RTLD_MAIN) == -1) 718 if (_rtld_load_needed_objects(_rtld_objmain, _RTLD_MAIN) == -1)
719 _rtld_die(); 719 _rtld_die();
720 720
721 dbg(("checking for required versions")); 721 dbg(("checking for required versions"));
722 for (obj = _rtld_objlist; obj != NULL; obj = obj->next) { 722 for (obj = _rtld_objlist; obj != NULL; obj = obj->next) {
723 if (_rtld_verify_object_versions(obj) == -1) 723 if (_rtld_verify_object_versions(obj) == -1)
724 _rtld_die(); 724 _rtld_die();
725 } 725 }
726 726
727#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) 727#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
728 dbg(("initializing initial Thread Local Storage offsets")); 728 dbg(("initializing initial Thread Local Storage offsets"));
729 /* 729 /*
730 * All initial objects get the TLS space from the static block. 730 * All initial objects get the TLS space from the static block.
731 */ 731 */
732 for (obj = _rtld_objlist; obj != NULL; obj = obj->next) 732 for (obj = _rtld_objlist; obj != NULL; obj = obj->next)
733 _rtld_tls_offset_allocate(obj); 733 _rtld_tls_offset_allocate(obj);
734#endif 734#endif
735 735
736 dbg(("relocating objects")); 736 dbg(("relocating objects"));
737 if (_rtld_relocate_objects(_rtld_objmain, bind_now) == -1) 737 if (_rtld_relocate_objects(_rtld_objmain, bind_now) == -1)
738 _rtld_die(); 738 _rtld_die();
739 739
740 dbg(("doing copy relocations")); 740 dbg(("doing copy relocations"));
741 if (_rtld_do_copy_relocations(_rtld_objmain) == -1) 741 if (_rtld_do_copy_relocations(_rtld_objmain) == -1)
742 _rtld_die(); 742 _rtld_die();
743 743
744#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) 744#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
745 dbg(("initializing Thread Local Storage for main thread")); 745 dbg(("initializing Thread Local Storage for main thread"));
746 /* 746 /*
747 * Set up TLS area for the main thread. 747 * Set up TLS area for the main thread.
748 * This has to be done after all relocations are processed, 748 * This has to be done after all relocations are processed,
749 * since .tdata may contain relocations. 749 * since .tdata may contain relocations.
750 */ 750 */
751 _rtld_tls_initial_allocation(); 751 _rtld_tls_initial_allocation();
752#endif 752#endif
753 753
754 /* 754 /*
755 * Set the __progname, environ and, __mainprog_obj before 755 * Set the __progname, environ and, __mainprog_obj before
756 * calling anything that might use them. 756 * calling anything that might use them.
757 */ 757 */
758 real___progname = _rtld_objmain_sym("__progname"); 758 real___progname = _rtld_objmain_sym("__progname");
759 if (real___progname) { 759 if (real___progname) {
760 if (argv[0] != NULL) { 760 if (argv[0] != NULL) {
761 if ((*real___progname = strrchr(argv[0], '/')) == NULL) 761 if ((*real___progname = strrchr(argv[0], '/')) == NULL)
762 (*real___progname) = argv[0]; 762 (*real___progname) = argv[0];
763 else 763 else
764 (*real___progname)++; 764 (*real___progname)++;
765 } else { 765 } else {
766 (*real___progname) = NULL; 766 (*real___progname) = NULL;
767 } 767 }
768 } 768 }
769 real_environ = _rtld_objmain_sym("environ"); 769 real_environ = _rtld_objmain_sym("environ");
770 if (real_environ) 770 if (real_environ)
771 *real_environ = environ; 771 *real_environ = environ;
772 /* 772 /*
773 * Set __mainprog_obj for old binaries. 773 * Set __mainprog_obj for old binaries.
774 */ 774 */
775 real___mainprog_obj = _rtld_objmain_sym("__mainprog_obj"); 775 real___mainprog_obj = _rtld_objmain_sym("__mainprog_obj");
776 if (real___mainprog_obj) 776 if (real___mainprog_obj)
777 *real___mainprog_obj = _rtld_objmain; 777 *real___mainprog_obj = _rtld_objmain;
778 778
779 _rtld_debug_state(); /* say hello to the debugger! */ 779 _rtld_debug_state(); /* say hello to the debugger! */
780 780
781 _rtld_exclusive_enter(&mask); 781 _rtld_exclusive_enter(&mask);
782 782
783 dbg(("calling _init functions")); 783 dbg(("calling _init functions"));
784 _rtld_call_init_functions(&mask); 784 _rtld_call_init_functions(&mask);
785 785
786 dbg(("control at program entry point = %p, obj = %p, exit = %p", 786 dbg(("control at program entry point = %p, obj = %p, exit = %p",
787 _rtld_objmain->entry, _rtld_objmain, _rtld_exit)); 787 _rtld_objmain->entry, _rtld_objmain, _rtld_exit));
788 788
789 _rtld_exclusive_exit(&mask); 789 _rtld_exclusive_exit(&mask);
790 790
791 /* 791 /*
792 * Return with the entry point and the exit procedure in at the top 792 * Return with the entry point and the exit procedure in at the top
793 * of stack. 793 * of stack.
794 */ 794 */
795 795
796 ((void **) osp)[0] = _rtld_exit; 796 ((void **) osp)[0] = _rtld_exit;
797 ((void **) osp)[1] = __UNCONST(_rtld_compat_obj); 797 ((void **) osp)[1] = __UNCONST(_rtld_compat_obj);
798 return (Elf_Addr) _rtld_objmain->entry; 798 return (Elf_Addr) _rtld_objmain->entry;
799} 799}
800 800
801void 801void
802_rtld_die(void) 802_rtld_die(void)
803{ 803{
804 const char *msg = dlerror(); 804 const char *msg = dlerror();
805 805
806 if (msg == NULL) 806 if (msg == NULL)
807 msg = "Fatal error"; 807 msg = "Fatal error";
808 xerrx(1, "%s", msg); 808 xerrx(1, "%s", msg);
809} 809}
810 810
811static Obj_Entry * 811static Obj_Entry *
812_rtld_dlcheck(void *handle) 812_rtld_dlcheck(void *handle)
813{ 813{
814 Obj_Entry *obj; 814 Obj_Entry *obj;
815 815
816 for (obj = _rtld_objlist; obj != NULL; obj = obj->next) 816 for (obj = _rtld_objlist; obj != NULL; obj = obj->next)
817 if (obj == (Obj_Entry *) handle) 817 if (obj == (Obj_Entry *) handle)
818 break; 818 break;
819 819
820 if (obj == NULL || obj->dl_refcount == 0) { 820 if (obj == NULL || obj->dl_refcount == 0) {
821 _rtld_error("Invalid shared object handle %p", handle); 821 _rtld_error("Invalid shared object handle %p", handle);
822 return NULL; 822 return NULL;
823 } 823 }
824 return obj; 824 return obj;
825} 825}
826 826
827static void 827static void
828_rtld_initlist_visit(Objlist* list, Obj_Entry *obj, int rev) 828_rtld_initlist_visit(Objlist* list, Obj_Entry *obj, int rev)
829{ 829{
830 Needed_Entry* elm; 830 Needed_Entry* elm;
831 831
832 /* dbg(("_rtld_initlist_visit(%s)", obj->path)); */ 832 /* dbg(("_rtld_initlist_visit(%s)", obj->path)); */
833 833
834 if (obj->init_done) 834 if (obj->init_done)
835 return; 835 return;
836 obj->init_done = 1; 836 obj->init_done = 1;
837 837
838 for (elm = obj->needed; elm != NULL; elm = elm->next) { 838 for (elm = obj->needed; elm != NULL; elm = elm->next) {
839 if (elm->obj != NULL) { 839 if (elm->obj != NULL) {
840 _rtld_initlist_visit(list, elm->obj, rev); 840 _rtld_initlist_visit(list, elm->obj, rev);
841 } 841 }
842 } 842 }
843 843
844 if (rev) { 844 if (rev) {
845 _rtld_objlist_push_head(list, obj); 845 _rtld_objlist_push_head(list, obj);
846 } else { 846 } else {
847 _rtld_objlist_push_tail(list, obj); 847 _rtld_objlist_push_tail(list, obj);
848 } 848 }
849} 849}
850 850
851static void 851static void
852_rtld_initlist_tsort(Objlist* list, int rev) 852_rtld_initlist_tsort(Objlist* list, int rev)
853{ 853{
854 dbg(("_rtld_initlist_tsort")); 854 dbg(("_rtld_initlist_tsort"));
855 855
856 Obj_Entry* obj; 856 Obj_Entry* obj;
857 857
858 /* 858 /*
859 * We don't include objmain here (starting from next) 859 * We don't include objmain here (starting from next)
860 * because csu handles it 860 * because csu handles it
861 */ 861 */
862 for (obj = _rtld_objlist->next; obj; obj = obj->next) { 862 for (obj = _rtld_objlist->next; obj; obj = obj->next) {
863 obj->init_done = 0; 863 obj->init_done = 0;
864 } 864 }
865 865
866 for (obj = _rtld_objlist->next; obj; obj = obj->next) { 866 for (obj = _rtld_objlist->next; obj; obj = obj->next) {
867 _rtld_initlist_visit(list, obj, rev); 867 _rtld_initlist_visit(list, obj, rev);
868 } 868 }
869} 869}
870 870
871static void 871static void
872_rtld_init_dag(Obj_Entry *root) 872_rtld_init_dag(Obj_Entry *root)
873{ 873{
874 874
875 _rtld_init_dag1(root, root); 875 _rtld_init_dag1(root, root);
876} 876}
877 877
878static void 878static void
879_rtld_init_dag1(Obj_Entry *root, Obj_Entry *obj) 879_rtld_init_dag1(Obj_Entry *root, Obj_Entry *obj)
880{ 880{
881 const Needed_Entry *needed; 881 const Needed_Entry *needed;
882 882
883 if (!obj->mainref) { 883 if (!obj->mainref) {
884 if (_rtld_objlist_find(&obj->dldags, root)) 884 if (_rtld_objlist_find(&obj->dldags, root))
885 return; 885 return;
886 dbg(("add %p (%s) to %p (%s) DAG", obj, obj->path, root, 886 dbg(("add %p (%s) to %p (%s) DAG", obj, obj->path, root,
887 root->path)); 887 root->path));
888 _rtld_objlist_push_tail(&obj->dldags, root); 888 _rtld_objlist_push_tail(&obj->dldags, root);
889 _rtld_objlist_push_tail(&root->dagmembers, obj); 889 _rtld_objlist_push_tail(&root->dagmembers, obj);
890 } 890 }
891 for (needed = obj->needed; needed != NULL; needed = needed->next) 891 for (needed = obj->needed; needed != NULL; needed = needed->next)
892 if (needed->obj != NULL) 892 if (needed->obj != NULL)
893 _rtld_init_dag1(root, needed->obj); 893 _rtld_init_dag1(root, needed->obj);
894} 894}
895 895
896/* 896/*
897 * Note, this is called only for objects loaded by dlopen(). 897 * Note, this is called only for objects loaded by dlopen().
898 */ 898 */
899static void 899static void
900_rtld_unload_object(sigset_t *mask, Obj_Entry *root, bool do_fini_funcs) 900_rtld_unload_object(sigset_t *mask, Obj_Entry *root, bool do_fini_funcs)
901{ 901{
902 902
903 _rtld_unref_dag(root); 903 _rtld_unref_dag(root);
904 if (root->refcount == 0) { /* We are finished with some objects. */ 904 if (root->refcount == 0) { /* We are finished with some objects. */
905 Obj_Entry *obj; 905 Obj_Entry *obj;
906 Obj_Entry **linkp; 906 Obj_Entry **linkp;
907 Objlist_Entry *elm; 907 Objlist_Entry *elm;
908 908
909 /* Finalize objects that are about to be unmapped. */ 909 /* Finalize objects that are about to be unmapped. */
910 if (do_fini_funcs) 910 if (do_fini_funcs)
911 _rtld_call_fini_functions(mask, 0); 911 _rtld_call_fini_functions(mask, 0);
912 912
913 /* Remove the DAG from all objects' DAG lists. */ 913 /* Remove the DAG from all objects' DAG lists. */
914 SIMPLEQ_FOREACH(elm, &root->dagmembers, link) 914 SIMPLEQ_FOREACH(elm, &root->dagmembers, link)
915 _rtld_objlist_remove(&elm->obj->dldags, root); 915 _rtld_objlist_remove(&elm->obj->dldags, root);
916 916
917 /* Remove the DAG from the RTLD_GLOBAL list. */ 917 /* Remove the DAG from the RTLD_GLOBAL list. */
918 if (root->globalref) { 918 if (root->globalref) {
919 root->globalref = 0; 919 root->globalref = 0;
920 _rtld_objlist_remove(&_rtld_list_global, root); 920 _rtld_objlist_remove(&_rtld_list_global, root);
921 } 921 }
922 922
923 /* Unmap all objects that are no longer referenced. */ 923 /* Unmap all objects that are no longer referenced. */
924 linkp = &_rtld_objlist->next; 924 linkp = &_rtld_objlist->next;
925 while ((obj = *linkp) != NULL) { 925 while ((obj = *linkp) != NULL) {
926 if (obj->refcount == 0) { 926 if (obj->refcount == 0) {
927 dbg(("unloading \"%s\"", obj->path)); 927 dbg(("unloading \"%s\"", obj->path));
928 if (obj->ehdr != MAP_FAILED) 928 if (obj->ehdr != MAP_FAILED)
929 munmap(obj->ehdr, _rtld_pagesz); 929 munmap(obj->ehdr, _rtld_pagesz);
930 munmap(obj->mapbase, obj->mapsize); 930 munmap(obj->mapbase, obj->mapsize);
931 _rtld_objlist_remove(&_rtld_list_global, obj); 931 _rtld_objlist_remove(&_rtld_list_global, obj);
932 _rtld_linkmap_delete(obj); 932 _rtld_linkmap_delete(obj);
933 *linkp = obj->next; 933 *linkp = obj->next;
934 _rtld_objcount--; 934 _rtld_objcount--;
935 _rtld_obj_free(obj); 935 _rtld_obj_free(obj);
936 } else 936 } else
937 linkp = &obj->next; 937 linkp = &obj->next;
938 } 938 }
939 _rtld_objtail = linkp; 939 _rtld_objtail = linkp;
940 } 940 }
941} 941}
942 942
943void 943void
944_rtld_ref_dag(Obj_Entry *root) 944_rtld_ref_dag(Obj_Entry *root)
945{ 945{
946 const Needed_Entry *needed; 946 const Needed_Entry *needed;
947 947
948 assert(root); 948 assert(root);
949 949
950 ++root->refcount; 950 ++root->refcount;
951 951
952 dbg(("incremented reference on \"%s\" (%d)", root->path, 952 dbg(("incremented reference on \"%s\" (%d)", root->path,
953 root->refcount)); 953 root->refcount));
954 for (needed = root->needed; needed != NULL; 954 for (needed = root->needed; needed != NULL;
955 needed = needed->next) { 955 needed = needed->next) {
956 if (needed->obj != NULL) 956 if (needed->obj != NULL)
957 _rtld_ref_dag(needed->obj); 957 _rtld_ref_dag(needed->obj);
958 } 958 }
959} 959}
960 960
961static void 961static void
962_rtld_unref_dag(Obj_Entry *root) 962_rtld_unref_dag(Obj_Entry *root)
963{ 963{
964 964
965 assert(root); 965 assert(root);
966 assert(root->refcount != 0); 966 assert(root->refcount != 0);
967 967
968 --root->refcount; 968 --root->refcount;
969 dbg(("decremented reference on \"%s\" (%d)", root->path, 969 dbg(("decremented reference on \"%s\" (%d)", root->path,
970 root->refcount)); 970 root->refcount));
971 971
972 if (root->refcount == 0) { 972 if (root->refcount == 0) {
973 const Needed_Entry *needed; 973 const Needed_Entry *needed;
974 974
975 for (needed = root->needed; needed != NULL; 975 for (needed = root->needed; needed != NULL;
976 needed = needed->next) { 976 needed = needed->next) {
977 if (needed->obj != NULL) 977 if (needed->obj != NULL)
978 _rtld_unref_dag(needed->obj); 978 _rtld_unref_dag(needed->obj);
979 } 979 }
980 } 980 }
981} 981}
982 982
983__strong_alias(__dlclose,dlclose) 983__strong_alias(__dlclose,dlclose)
984int 984int
985dlclose(void *handle) 985dlclose(void *handle)
986{ 986{
987 Obj_Entry *root; 987 Obj_Entry *root;
988 sigset_t mask; 988 sigset_t mask;
989 989
990 dbg(("dlclose of %p", handle)); 990 dbg(("dlclose of %p", handle));
991 991
992 _rtld_exclusive_enter(&mask); 992 _rtld_exclusive_enter(&mask);
993 993
994 root = _rtld_dlcheck(handle); 994 root = _rtld_dlcheck(handle);
995 995
996 if (root == NULL) { 996 if (root == NULL) {
997 _rtld_exclusive_exit(&mask); 997 _rtld_exclusive_exit(&mask);
998 return -1; 998 return -1;
999 } 999 }
1000 1000
1001 _rtld_debug.r_state = RT_DELETE; 1001 _rtld_debug.r_state = RT_DELETE;
1002 _rtld_debug_state(); 1002 _rtld_debug_state();
1003 1003
1004 --root->dl_refcount; 1004 --root->dl_refcount;
1005 _rtld_unload_object(&mask, root, true); 1005 _rtld_unload_object(&mask, root, true);
1006 1006
1007 _rtld_debug.r_state = RT_CONSISTENT; 1007 _rtld_debug.r_state = RT_CONSISTENT;
1008 _rtld_debug_state(); 1008 _rtld_debug_state();
1009 1009
1010 _rtld_exclusive_exit(&mask); 1010 _rtld_exclusive_exit(&mask);
1011 1011
1012 return 0; 1012 return 0;
1013} 1013}
1014 1014
1015__strong_alias(__dlerror,dlerror) 1015__strong_alias(__dlerror,dlerror)
1016char * 1016char *
1017dlerror(void) 1017dlerror(void)
1018{ 1018{
1019 char *msg = error_message; 1019 char *msg = error_message;
1020 1020
1021 error_message = NULL; 1021 error_message = NULL;
1022 return msg; 1022 return msg;
1023} 1023}
1024 1024
1025__strong_alias(__dlopen,dlopen) 1025__strong_alias(__dlopen,dlopen)
1026void * 1026void *
1027dlopen(const char *name, int mode) 1027dlopen(const char *name, int mode)
1028{ 1028{
1029 Obj_Entry **old_obj_tail = _rtld_objtail; 1029 Obj_Entry **old_obj_tail = _rtld_objtail;
1030 Obj_Entry *obj = NULL; 1030 Obj_Entry *obj = NULL;
1031 int flags = _RTLD_DLOPEN; 1031 int flags = _RTLD_DLOPEN;
1032 bool nodelete; 1032 bool nodelete;
1033 bool now; 1033 bool now;
1034 sigset_t mask; 1034 sigset_t mask;
1035 int result; 1035 int result;
1036 1036
1037 dbg(("dlopen of %s %d", name, mode)); 1037 dbg(("dlopen of %s %d", name, mode));
1038 1038
1039 _rtld_exclusive_enter(&mask); 1039 _rtld_exclusive_enter(&mask);
1040 1040
1041 flags |= (mode & RTLD_GLOBAL) ? _RTLD_GLOBAL : 0; 1041 flags |= (mode & RTLD_GLOBAL) ? _RTLD_GLOBAL : 0;
1042 flags |= (mode & RTLD_NOLOAD) ? _RTLD_NOLOAD : 0; 1042 flags |= (mode & RTLD_NOLOAD) ? _RTLD_NOLOAD : 0;
1043 1043
1044 nodelete = (mode & RTLD_NODELETE) ? true : false; 1044 nodelete = (mode & RTLD_NODELETE) ? true : false;
1045 now = ((mode & RTLD_MODEMASK) == RTLD_NOW) ? true : false; 1045 now = ((mode & RTLD_MODEMASK) == RTLD_NOW) ? true : false;
1046 1046
1047 _rtld_debug.r_state = RT_ADD; 1047 _rtld_debug.r_state = RT_ADD;
1048 _rtld_debug_state(); 1048 _rtld_debug_state();
1049 1049
1050 if (name == NULL) { 1050 if (name == NULL) {
1051 obj = _rtld_objmain; 1051 obj = _rtld_objmain;
1052 obj->refcount++; 1052 obj->refcount++;
1053 } else 1053 } else
1054 obj = _rtld_load_library(name, _rtld_objmain, flags); 1054 obj = _rtld_load_library(name, _rtld_objmain, flags);
1055 1055
1056 1056
1057 if (obj != NULL) { 1057 if (obj != NULL) {
1058 ++obj->dl_refcount; 1058 ++obj->dl_refcount;
1059 if (*old_obj_tail != NULL) { /* We loaded something new. */ 1059 if (*old_obj_tail != NULL) { /* We loaded something new. */
1060 assert(*old_obj_tail == obj); 1060 assert(*old_obj_tail == obj);
1061 1061
1062 result = _rtld_load_needed_objects(obj, flags); 1062 result = _rtld_load_needed_objects(obj, flags);
1063 if (result != -1) { 1063 if (result != -1) {
1064 Objlist_Entry *entry; 1064 Objlist_Entry *entry;
1065 _rtld_init_dag(obj); 1065 _rtld_init_dag(obj);
1066 SIMPLEQ_FOREACH(entry, &obj->dagmembers, link) { 1066 SIMPLEQ_FOREACH(entry, &obj->dagmembers, link) {
1067 result = _rtld_verify_object_versions(entry->obj); 1067 result = _rtld_verify_object_versions(entry->obj);
1068 if (result == -1) 1068 if (result == -1)
1069 break; 1069 break;
1070 } 1070 }
1071 } 1071 }
1072 if (result == -1 || _rtld_relocate_objects(obj, 1072 if (result == -1 || _rtld_relocate_objects(obj,
1073 (now || obj->z_now)) == -1) { 1073 (now || obj->z_now)) == -1) {
1074 _rtld_unload_object(&mask, obj, false); 1074 _rtld_unload_object(&mask, obj, false);
1075 obj->dl_refcount--; 1075 obj->dl_refcount--;
1076 obj = NULL; 1076 obj = NULL;
1077 } else { 1077 } else {
1078 _rtld_call_init_functions(&mask); 1078 _rtld_call_init_functions(&mask);
1079 } 1079 }
1080 } 1080 }
1081 if (obj != NULL) { 1081 if (obj != NULL) {
1082 if ((nodelete || obj->z_nodelete) && !obj->ref_nodel) { 1082 if ((nodelete || obj->z_nodelete) && !obj->ref_nodel) {
1083 dbg(("dlopen obj %s nodelete", obj->path)); 1083 dbg(("dlopen obj %s nodelete", obj->path));
1084 _rtld_ref_dag(obj); 1084 _rtld_ref_dag(obj);
1085 obj->z_nodelete = obj->ref_nodel = true; 1085 obj->z_nodelete = obj->ref_nodel = true;
1086 } 1086 }
1087 } 1087 }
1088 } 1088 }
1089 _rtld_debug.r_state = RT_CONSISTENT; 1089 _rtld_debug.r_state = RT_CONSISTENT;
1090 _rtld_debug_state(); 1090 _rtld_debug_state();
1091 1091
1092 _rtld_exclusive_exit(&mask); 1092 _rtld_exclusive_exit(&mask);
1093 1093
1094 return obj; 1094 return obj;
1095} 1095}
1096 1096
1097/* 1097/*
1098 * Find a symbol in the main program. 1098 * Find a symbol in the main program.
1099 */ 1099 */
1100void * 1100void *
1101_rtld_objmain_sym(const char *name) 1101_rtld_objmain_sym(const char *name)
1102{ 1102{
1103 Elf_Hash hash; 1103 Elf_Hash hash;
1104 const Elf_Sym *def; 1104 const Elf_Sym *def;
1105 const Obj_Entry *obj; 1105 const Obj_Entry *obj;
1106 DoneList donelist; 1106 DoneList donelist;
1107 1107
1108 hash.sysv = _rtld_sysv_hash(name); 1108 hash.sysv = _rtld_sysv_hash(name);
1109 hash.gnu = _rtld_gnu_hash(name); 1109 hash.gnu = _rtld_gnu_hash(name);
1110 obj = _rtld_objmain; 1110 obj = _rtld_objmain;
1111 _rtld_donelist_init(&donelist); 1111 _rtld_donelist_init(&donelist);
1112 1112
1113 def = _rtld_symlook_list(name, &hash, &_rtld_list_main, &obj, 0, 1113 def = _rtld_symlook_list(name, &hash, &_rtld_list_main, &obj, 0,
1114 NULL, &donelist); 1114 NULL, &donelist);
1115 1115
1116 if (def != NULL) 1116 if (def != NULL)
1117 return obj->relocbase + def->st_value; 1117 return obj->relocbase + def->st_value;
1118 return NULL; 1118 return NULL;
1119} 1119}
1120 1120
1121#ifdef __powerpc__ 1121#if defined(__powerpc__) && !defined(__clang__)
1122static __noinline void * 1122static __noinline void *
1123hackish_return_address(void) 1123hackish_return_address(void)
1124{ 1124{
1125#if __GNUC_PREREQ__(6,0) 1125#if __GNUC_PREREQ__(6,0)
1126#pragma GCC diagnostic push 1126#pragma GCC diagnostic push
1127#pragma GCC diagnostic ignored "-Wframe-address" 1127#pragma GCC diagnostic ignored "-Wframe-address"
1128#endif 1128#endif
1129 return __builtin_return_address(1); 1129 return __builtin_return_address(1);
1130#if __GNUC_PREREQ__(6,0) 1130#if __GNUC_PREREQ__(6,0)
1131#pragma GCC diagnostic pop 1131#pragma GCC diagnostic pop
1132#endif 1132#endif
1133} 1133}
1134#endif 1134#endif
1135 1135
1136#ifdef __HAVE_FUNCTION_DESCRIPTORS 1136#ifdef __HAVE_FUNCTION_DESCRIPTORS
1137#define lookup_mutex_enter() _rtld_exclusive_enter(&mask) 1137#define lookup_mutex_enter() _rtld_exclusive_enter(&mask)
1138#define lookup_mutex_exit() _rtld_exclusive_exit(&mask) 1138#define lookup_mutex_exit() _rtld_exclusive_exit(&mask)
1139#else 1139#else
1140#define lookup_mutex_enter() _rtld_shared_enter() 1140#define lookup_mutex_enter() _rtld_shared_enter()
1141#define lookup_mutex_exit() _rtld_shared_exit() 1141#define lookup_mutex_exit() _rtld_shared_exit()
1142#endif 1142#endif
1143 1143
1144static void * 1144static void *
1145do_dlsym(void *handle, const char *name, const Ver_Entry *ventry, void *retaddr) 1145do_dlsym(void *handle, const char *name, const Ver_Entry *ventry, void *retaddr)
1146{ 1146{
1147 const Obj_Entry *obj; 1147 const Obj_Entry *obj;
1148 Elf_Hash hash; 1148 Elf_Hash hash;
1149 const Elf_Sym *def; 1149 const Elf_Sym *def;
1150 const Obj_Entry *defobj; 1150 const Obj_Entry *defobj;
1151 DoneList donelist; 1151 DoneList donelist;
1152 const u_int flags = SYMLOOK_DLSYM | SYMLOOK_IN_PLT; 1152 const u_int flags = SYMLOOK_DLSYM | SYMLOOK_IN_PLT;
1153#ifdef __HAVE_FUNCTION_DESCRIPTORS 1153#ifdef __HAVE_FUNCTION_DESCRIPTORS
1154 sigset_t mask; 1154 sigset_t mask;
1155#endif 1155#endif
1156 1156
1157 lookup_mutex_enter(); 1157 lookup_mutex_enter();
1158 1158
1159 hash.sysv = _rtld_sysv_hash(name); 1159 hash.sysv = _rtld_sysv_hash(name);
1160 hash.gnu = _rtld_gnu_hash(name); 1160 hash.gnu = _rtld_gnu_hash(name);
1161 def = NULL; 1161 def = NULL;
1162 defobj = NULL; 1162 defobj = NULL;
1163 1163
1164 switch ((intptr_t)handle) { 1164 switch ((intptr_t)handle) {
1165 case (intptr_t)NULL: 1165 case (intptr_t)NULL:
1166 case (intptr_t)RTLD_NEXT: 1166 case (intptr_t)RTLD_NEXT:
1167 case (intptr_t)RTLD_DEFAULT: 1167 case (intptr_t)RTLD_DEFAULT:
1168 case (intptr_t)RTLD_SELF: 1168 case (intptr_t)RTLD_SELF:
1169 if ((obj = _rtld_obj_from_addr(retaddr)) == NULL) { 1169 if ((obj = _rtld_obj_from_addr(retaddr)) == NULL) {
1170 _rtld_error("Cannot determine caller's shared object"); 1170 _rtld_error("Cannot determine caller's shared object");
1171 lookup_mutex_exit(); 1171 lookup_mutex_exit();
1172 return NULL; 1172 return NULL;
1173 } 1173 }
1174 1174
1175 switch ((intptr_t)handle) { 1175 switch ((intptr_t)handle) {
1176 case (intptr_t)NULL: /* Just the caller's shared object. */ 1176 case (intptr_t)NULL: /* Just the caller's shared object. */
1177 def = _rtld_symlook_obj(name, &hash, obj, flags, ventry); 1177 def = _rtld_symlook_obj(name, &hash, obj, flags, ventry);
1178 defobj = obj; 1178 defobj = obj;
1179 break; 1179 break;
1180 1180
1181 case (intptr_t)RTLD_NEXT: /* Objects after callers */ 1181 case (intptr_t)RTLD_NEXT: /* Objects after callers */
1182 obj = obj->next; 1182 obj = obj->next;
1183 /*FALLTHROUGH*/ 1183 /*FALLTHROUGH*/
1184 1184
1185 case (intptr_t)RTLD_SELF: /* Caller included */ 1185 case (intptr_t)RTLD_SELF: /* Caller included */
1186 for (; obj; obj = obj->next) { 1186 for (; obj; obj = obj->next) {
1187 if ((def = _rtld_symlook_obj(name, &hash, obj, 1187 if ((def = _rtld_symlook_obj(name, &hash, obj,
1188 flags, ventry)) != NULL) { 1188 flags, ventry)) != NULL) {
1189 defobj = obj; 1189 defobj = obj;
1190 break; 1190 break;
1191 } 1191 }
1192 } 1192 }
1193 /* 1193 /*
1194 * Search the dynamic linker itself, and possibly 1194 * Search the dynamic linker itself, and possibly
1195 * resolve the symbol from there if it is not defined 1195 * resolve the symbol from there if it is not defined
1196 * already or weak. This is how the application links 1196 * already or weak. This is how the application links
1197 * to dynamic linker services such as dlopen. 1197 * to dynamic linker services such as dlopen.
1198 */ 1198 */
1199 if (!def || ELF_ST_BIND(def->st_info) == STB_WEAK) { 1199 if (!def || ELF_ST_BIND(def->st_info) == STB_WEAK) {
1200 const Elf_Sym *symp = _rtld_symlook_obj(name, 1200 const Elf_Sym *symp = _rtld_symlook_obj(name,
1201 &hash, &_rtld_objself, flags, ventry); 1201 &hash, &_rtld_objself, flags, ventry);
1202 if (symp != NULL) { 1202 if (symp != NULL) {
1203 def = symp; 1203 def = symp;
1204 defobj = &_rtld_objself; 1204 defobj = &_rtld_objself;
1205 } 1205 }
1206 } 1206 }
1207 break; 1207 break;
1208 1208
1209 case (intptr_t)RTLD_DEFAULT: 1209 case (intptr_t)RTLD_DEFAULT:
1210 def = _rtld_symlook_default(name, &hash, obj, &defobj, 1210 def = _rtld_symlook_default(name, &hash, obj, &defobj,
1211 flags, ventry); 1211 flags, ventry);
1212 break; 1212 break;
1213 1213
1214 default: 1214 default:
1215 abort(); 1215 abort();
1216 } 1216 }
1217 break; 1217 break;
1218 1218
1219 default: 1219 default:
1220 if ((obj = _rtld_dlcheck(handle)) == NULL) { 1220 if ((obj = _rtld_dlcheck(handle)) == NULL) {
1221 lookup_mutex_exit(); 1221 lookup_mutex_exit();
1222 return NULL; 1222 return NULL;
1223 } 1223 }
1224 1224
1225 _rtld_donelist_init(&donelist); 1225 _rtld_donelist_init(&donelist);
1226 1226
1227 if (obj->mainprog) { 1227 if (obj->mainprog) {
1228 /* Search main program and all libraries loaded by it */ 1228 /* Search main program and all libraries loaded by it */
1229 def = _rtld_symlook_list(name, &hash, &_rtld_list_main, 1229 def = _rtld_symlook_list(name, &hash, &_rtld_list_main,
1230 &defobj, flags, ventry, &donelist); 1230 &defobj, flags, ventry, &donelist);
1231 } else { 1231 } else {
1232 Needed_Entry fake; 1232 Needed_Entry fake;
1233 DoneList depth; 1233 DoneList depth;
1234 1234
1235 /* Search the object and all the libraries loaded by it. */ 1235 /* Search the object and all the libraries loaded by it. */
1236 fake.next = NULL; 1236 fake.next = NULL;
1237 fake.obj = __UNCONST(obj); 1237 fake.obj = __UNCONST(obj);
1238 fake.name = 0; 1238 fake.name = 0;
1239 1239
1240 _rtld_donelist_init(&depth); 1240 _rtld_donelist_init(&depth);
1241 def = _rtld_symlook_needed(name, &hash, &fake, &defobj, 1241 def = _rtld_symlook_needed(name, &hash, &fake, &defobj,
1242 flags, ventry, &donelist, &depth); 1242 flags, ventry, &donelist, &depth);
1243 } 1243 }
1244 1244
1245 break; 1245 break;
1246 } 1246 }
1247 1247
1248 if (def != NULL) { 1248 if (def != NULL) {
1249 void *p; 1249 void *p;
1250 1250
1251 if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { 1251 if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
1252#ifdef __HAVE_FUNCTION_DESCRIPTORS 1252#ifdef __HAVE_FUNCTION_DESCRIPTORS
1253 lookup_mutex_exit(); 1253 lookup_mutex_exit();
1254 _rtld_shared_enter(); 1254 _rtld_shared_enter();
1255#endif 1255#endif
1256 p = (void *)_rtld_resolve_ifunc(defobj, def); 1256 p = (void *)_rtld_resolve_ifunc(defobj, def);
1257 _rtld_shared_exit(); 1257 _rtld_shared_exit();
1258 return p; 1258 return p;
1259 } 1259 }
1260 1260
1261#ifdef __HAVE_FUNCTION_DESCRIPTORS 1261#ifdef __HAVE_FUNCTION_DESCRIPTORS
1262 if (ELF_ST_TYPE(def->st_info) == STT_FUNC) { 1262 if (ELF_ST_TYPE(def->st_info) == STT_FUNC) {
1263 p = (void *)_rtld_function_descriptor_alloc(defobj, 1263 p = (void *)_rtld_function_descriptor_alloc(defobj,
1264 def, 0); 1264 def, 0);
1265 lookup_mutex_exit(); 1265 lookup_mutex_exit();
1266 return p; 1266 return p;
1267 } 1267 }
1268#endif /* __HAVE_FUNCTION_DESCRIPTORS */ 1268#endif /* __HAVE_FUNCTION_DESCRIPTORS */
1269 p = defobj->relocbase + def->st_value; 1269 p = defobj->relocbase + def->st_value;
1270 lookup_mutex_exit(); 1270 lookup_mutex_exit();
1271 return p; 1271 return p;
1272 } 1272 }
1273 1273
1274 _rtld_error("Undefined symbol \"%s\"", name); 1274 _rtld_error("Undefined symbol \"%s\"", name);
1275 lookup_mutex_exit(); 1275 lookup_mutex_exit();
1276 return NULL; 1276 return NULL;
1277} 1277}
1278 1278
1279__strong_alias(__dlsym,dlsym) 1279__strong_alias(__dlsym,dlsym)
1280void * 1280void *
1281dlsym(void *handle, const char *name) 1281dlsym(void *handle, const char *name)
1282{ 1282{
1283 void *retaddr; 1283 void *retaddr;
1284 1284
1285 dbg(("dlsym of %s in %p", name, handle)); 1285 dbg(("dlsym of %s in %p", name, handle));
1286 1286
1287#ifdef __powerpc__ 1287#if defined(__powerpc__) && !defined(__clang__)
1288 retaddr = hackish_return_address(); 1288 retaddr = hackish_return_address();
1289#else 1289#else
1290 retaddr = __builtin_return_address(0); 1290 retaddr = __builtin_return_address(0);
1291#endif 1291#endif
1292 return do_dlsym(handle, name, NULL, retaddr); 1292 return do_dlsym(handle, name, NULL, retaddr);
1293} 1293}
1294 1294
1295__strong_alias(__dlvsym,dlvsym) 1295__strong_alias(__dlvsym,dlvsym)
1296void * 1296void *
1297dlvsym(void *handle, const char *name, const char *version) 1297dlvsym(void *handle, const char *name, const char *version)
1298{ 1298{
1299 Ver_Entry *ventry = NULL; 1299 Ver_Entry *ventry = NULL;
1300 Ver_Entry ver_entry; 1300 Ver_Entry ver_entry;
1301 void *retaddr; 1301 void *retaddr;
1302 1302
1303 dbg(("dlvsym of %s@%s in %p", name, version ? version : NULL, handle)); 1303 dbg(("dlvsym of %s@%s in %p", name, version ? version : NULL, handle));
1304 1304
1305 if (version != NULL) { 1305 if (version != NULL) {
1306 ver_entry.name = version; 1306 ver_entry.name = version;
1307 ver_entry.file = NULL; 1307 ver_entry.file = NULL;
1308 ver_entry.hash = _rtld_sysv_hash(version); 1308 ver_entry.hash = _rtld_sysv_hash(version);
1309 ver_entry.flags = 0; 1309 ver_entry.flags = 0;
1310 ventry = &ver_entry; 1310 ventry = &ver_entry;
1311 } 1311 }
1312#ifdef __powerpc__ 1312#if defined(__powerpc__) && !defined(__clang__)
1313 retaddr = hackish_return_address(); 1313 retaddr = hackish_return_address();
1314#else 1314#else
1315 retaddr = __builtin_return_address(0); 1315 retaddr = __builtin_return_address(0);
1316#endif 1316#endif
1317 return do_dlsym(handle, name, ventry, retaddr); 1317 return do_dlsym(handle, name, ventry, retaddr);
1318} 1318}
1319 1319
1320__strong_alias(__dladdr,dladdr) 1320__strong_alias(__dladdr,dladdr)
1321int 1321int
1322dladdr(const void *addr, Dl_info *info) 1322dladdr(const void *addr, Dl_info *info)
1323{ 1323{
1324 const Obj_Entry *obj; 1324 const Obj_Entry *obj;
1325 const Elf_Sym *def, *best_def; 1325 const Elf_Sym *def, *best_def;
1326 void *symbol_addr; 1326 void *symbol_addr;
1327 unsigned long symoffset; 1327 unsigned long symoffset;
1328#ifdef __HAVE_FUNCTION_DESCRIPTORS 1328#ifdef __HAVE_FUNCTION_DESCRIPTORS
1329 sigset_t mask; 1329 sigset_t mask;
1330#endif 1330#endif
1331 1331
1332 dbg(("dladdr of %p", addr)); 1332 dbg(("dladdr of %p", addr));
1333 1333
1334 lookup_mutex_enter(); 1334 lookup_mutex_enter();
1335 1335
1336#ifdef __HAVE_FUNCTION_DESCRIPTORS 1336#ifdef __HAVE_FUNCTION_DESCRIPTORS
1337 addr = _rtld_function_descriptor_function(addr); 1337 addr = _rtld_function_descriptor_function(addr);
1338#endif /* __HAVE_FUNCTION_DESCRIPTORS */ 1338#endif /* __HAVE_FUNCTION_DESCRIPTORS */
1339 1339
1340 obj = _rtld_obj_from_addr(addr); 1340 obj = _rtld_obj_from_addr(addr);
1341 if (obj == NULL) { 1341 if (obj == NULL) {
1342 _rtld_error("No shared object contains address"); 1342 _rtld_error("No shared object contains address");
1343 lookup_mutex_exit(); 1343 lookup_mutex_exit();
1344 return 0; 1344 return 0;
1345 } 1345 }
1346 info->dli_fname = obj->path; 1346 info->dli_fname = obj->path;
1347 info->dli_fbase = obj->mapbase; 1347 info->dli_fbase = obj->mapbase;
1348 info->dli_saddr = (void *)0; 1348 info->dli_saddr = (void *)0;
1349 info->dli_sname = NULL; 1349 info->dli_sname = NULL;
1350 1350
1351 /* 1351 /*
1352 * Walk the symbol list looking for the symbol whose address is 1352 * Walk the symbol list looking for the symbol whose address is
1353 * closest to the address sent in. 1353 * closest to the address sent in.
1354 */ 1354 */
1355 best_def = NULL; 1355 best_def = NULL;
1356 for (symoffset = 0; symoffset < obj->nchains; symoffset++) { 1356 for (symoffset = 0; symoffset < obj->nchains; symoffset++) {
1357 def = obj->symtab + symoffset; 1357 def = obj->symtab + symoffset;
1358 1358
1359 /* 1359 /*
1360 * For skip the symbol if st_shndx is either SHN_UNDEF or 1360 * For skip the symbol if st_shndx is either SHN_UNDEF or
1361 * SHN_COMMON. 1361 * SHN_COMMON.
1362 */ 1362 */
1363 if (def->st_shndx == SHN_UNDEF || def->st_shndx == SHN_COMMON) 1363 if (def->st_shndx == SHN_UNDEF || def->st_shndx == SHN_COMMON)
1364 continue; 1364 continue;
1365 1365
1366 /* 1366 /*
1367 * If the symbol is greater than the specified address, or if it 1367 * If the symbol is greater than the specified address, or if it
1368 * is further away from addr than the current nearest symbol, 1368 * is further away from addr than the current nearest symbol,
1369 * then reject it. 1369 * then reject it.
1370 */ 1370 */
1371 symbol_addr = obj->relocbase + def->st_value; 1371 symbol_addr = obj->relocbase + def->st_value;
1372 if (symbol_addr > addr || symbol_addr < info->dli_saddr) 1372 if (symbol_addr > addr || symbol_addr < info->dli_saddr)
1373 continue; 1373 continue;
1374 1374
1375 /* Update our idea of the nearest symbol. */ 1375 /* Update our idea of the nearest symbol. */
1376 info->dli_sname = obj->strtab + def->st_name; 1376 info->dli_sname = obj->strtab + def->st_name;
1377 info->dli_saddr = symbol_addr; 1377 info->dli_saddr = symbol_addr;
1378 best_def = def; 1378 best_def = def;
1379 1379
1380 1380
1381 /* Exact match? */ 1381 /* Exact match? */
1382 if (info->dli_saddr == addr) 1382 if (info->dli_saddr == addr)
1383 break; 1383 break;
1384 } 1384 }
1385 1385
1386#ifdef __HAVE_FUNCTION_DESCRIPTORS 1386#ifdef __HAVE_FUNCTION_DESCRIPTORS
1387 if (best_def != NULL && ELF_ST_TYPE(best_def->st_info) == STT_FUNC) 1387 if (best_def != NULL && ELF_ST_TYPE(best_def->st_info) == STT_FUNC)
1388 info->dli_saddr = (void *)_rtld_function_descriptor_alloc(obj, 1388 info->dli_saddr = (void *)_rtld_function_descriptor_alloc(obj,
1389 best_def, 0); 1389 best_def, 0);
1390#else 1390#else
1391 __USE(best_def); 1391 __USE(best_def);
1392#endif /* __HAVE_FUNCTION_DESCRIPTORS */ 1392#endif /* __HAVE_FUNCTION_DESCRIPTORS */
1393 1393
1394 lookup_mutex_exit(); 1394 lookup_mutex_exit();
1395 return 1; 1395 return 1;
1396} 1396}
1397 1397
1398__strong_alias(__dlinfo,dlinfo) 1398__strong_alias(__dlinfo,dlinfo)
1399int 1399int
1400dlinfo(void *handle, int req, void *v) 1400dlinfo(void *handle, int req, void *v)
1401{ 1401{
1402 const Obj_Entry *obj; 1402 const Obj_Entry *obj;
1403 void *retaddr; 1403 void *retaddr;
1404 1404
1405 dbg(("dlinfo for %p %d", handle, req)); 1405 dbg(("dlinfo for %p %d", handle, req));
1406 1406
1407 _rtld_shared_enter(); 1407 _rtld_shared_enter();
1408 1408
1409 if (handle == RTLD_SELF) { 1409 if (handle == RTLD_SELF) {
1410#ifdef __powerpc__ 1410#if defined(__powerpc__) && !defined(__clang__)
1411 retaddr = hackish_return_address(); 1411 retaddr = hackish_return_address();
1412#else 1412#else
1413 retaddr = __builtin_return_address(0); 1413 retaddr = __builtin_return_address(0);
1414#endif 1414#endif
1415 if ((obj = _rtld_obj_from_addr(retaddr)) == NULL) { 1415 if ((obj = _rtld_obj_from_addr(retaddr)) == NULL) {
1416 _rtld_error("Cannot determine caller's shared object"); 1416 _rtld_error("Cannot determine caller's shared object");
1417 _rtld_shared_exit(); 1417 _rtld_shared_exit();
1418 return -1; 1418 return -1;
1419 } 1419 }
1420 } else { 1420 } else {
1421 if ((obj = _rtld_dlcheck(handle)) == NULL) { 1421 if ((obj = _rtld_dlcheck(handle)) == NULL) {
1422 _rtld_shared_exit(); 1422 _rtld_shared_exit();
1423 return -1; 1423 return -1;
1424 } 1424 }
1425 } 1425 }
1426 1426
1427 switch (req) { 1427 switch (req) {
1428 case RTLD_DI_LINKMAP: 1428 case RTLD_DI_LINKMAP:
1429 { 1429 {
1430 const struct link_map **map = v; 1430 const struct link_map **map = v;
1431 1431
1432 *map = &obj->linkmap; 1432 *map = &obj->linkmap;
1433 break; 1433 break;
1434 } 1434 }
1435 1435
1436 default: 1436 default:
1437 _rtld_error("Invalid request"); 1437 _rtld_error("Invalid request");
1438 _rtld_shared_exit(); 1438 _rtld_shared_exit();
1439 return -1; 1439 return -1;
1440 } 1440 }
1441 1441
1442 _rtld_shared_exit(); 1442 _rtld_shared_exit();
1443 return 0; 1443 return 0;
1444} 1444}
1445 1445
1446static void 1446static void
1447_rtld_fill_dl_phdr_info(const Obj_Entry *obj, struct dl_phdr_info *phdr_info) 1447_rtld_fill_dl_phdr_info(const Obj_Entry *obj, struct dl_phdr_info *phdr_info)
1448{ 1448{
1449 1449
1450 phdr_info->dlpi_addr = (Elf_Addr)obj->relocbase; 1450 phdr_info->dlpi_addr = (Elf_Addr)obj->relocbase;
1451 /* XXX: wrong but not fixing it yet */ 1451 /* XXX: wrong but not fixing it yet */
1452 phdr_info->dlpi_name = obj->path; 1452 phdr_info->dlpi_name = obj->path;
1453 phdr_info->dlpi_phdr = obj->phdr; 1453 phdr_info->dlpi_phdr = obj->phdr;
1454 phdr_info->dlpi_phnum = obj->phsize / sizeof(obj->phdr[0]); 1454 phdr_info->dlpi_phnum = obj->phsize / sizeof(obj->phdr[0]);
1455#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) 1455#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
1456 phdr_info->dlpi_tls_modid = obj->tlsindex; 1456 phdr_info->dlpi_tls_modid = obj->tlsindex;
1457 phdr_info->dlpi_tls_data = obj->tlsinit; 1457 phdr_info->dlpi_tls_data = obj->tlsinit;
1458#else 1458#else
1459 phdr_info->dlpi_tls_modid = 0; 1459 phdr_info->dlpi_tls_modid = 0;
1460 phdr_info->dlpi_tls_data = 0; 1460 phdr_info->dlpi_tls_data = 0;
1461#endif 1461#endif
1462 phdr_info->dlpi_adds = _rtld_objloads; 1462 phdr_info->dlpi_adds = _rtld_objloads;
1463 phdr_info->dlpi_subs = _rtld_objloads - _rtld_objcount; 1463 phdr_info->dlpi_subs = _rtld_objloads - _rtld_objcount;
1464} 1464}
1465 1465
1466__strong_alias(__dl_iterate_phdr,dl_iterate_phdr); 1466__strong_alias(__dl_iterate_phdr,dl_iterate_phdr);
1467int 1467int
1468dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), void *param) 1468dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), void *param)
1469{ 1469{
1470 struct dl_phdr_info phdr_info; 1470 struct dl_phdr_info phdr_info;
1471 const Obj_Entry *obj; 1471 const Obj_Entry *obj;
1472 int error = 0; 1472 int error = 0;
1473 1473
1474 dbg(("dl_iterate_phdr")); 1474 dbg(("dl_iterate_phdr"));
1475 1475
1476 _rtld_shared_enter(); 1476 _rtld_shared_enter();
1477 1477
1478 for (obj = _rtld_objlist; obj != NULL; obj = obj->next) { 1478 for (obj = _rtld_objlist; obj != NULL; obj = obj->next) {
1479 _rtld_fill_dl_phdr_info(obj, &phdr_info); 1479 _rtld_fill_dl_phdr_info(obj, &phdr_info);
1480 1480
1481 /* XXXlocking: exit point */ 1481 /* XXXlocking: exit point */
1482 error = callback(&phdr_info, sizeof(phdr_info), param); 1482 error = callback(&phdr_info, sizeof(phdr_info), param);
1483 if (error) 1483 if (error)
1484 break; 1484 break;
1485 } 1485 }
1486 1486
1487 if (error == 0) { 1487 if (error == 0) {
1488 _rtld_fill_dl_phdr_info(&_rtld_objself, &phdr_info); 1488 _rtld_fill_dl_phdr_info(&_rtld_objself, &phdr_info);
1489 1489
1490 /* XXXlocking: exit point */ 1490 /* XXXlocking: exit point */
1491 error = callback(&phdr_info, sizeof(phdr_info), param); 1491 error = callback(&phdr_info, sizeof(phdr_info), param);
1492 } 1492 }
1493 1493
1494 _rtld_shared_exit(); 1494 _rtld_shared_exit();
1495 return error; 1495 return error;
1496} 1496}
1497 1497
1498void 1498void
1499__dl_cxa_refcount(void *addr, ssize_t delta) 1499__dl_cxa_refcount(void *addr, ssize_t delta)
1500{ 1500{
1501 sigset_t mask; 1501 sigset_t mask;
1502 Obj_Entry *obj; 1502 Obj_Entry *obj;
1503 1503
1504 if (delta == 0) 1504 if (delta == 0)
1505 return; 1505 return;
1506 1506
1507 dbg(("__dl_cxa_refcount of %p with %zd", addr, delta)); 1507 dbg(("__dl_cxa_refcount of %p with %zd", addr, delta));
1508 1508
1509 _rtld_exclusive_enter(&mask); 1509 _rtld_exclusive_enter(&mask);
1510 obj = _rtld_obj_from_addr(addr); 1510 obj = _rtld_obj_from_addr(addr);
1511 1511
1512 if (obj == NULL) { 1512 if (obj == NULL) {
1513 dbg(("__dl_cxa_refcont: address not found")); 1513 dbg(("__dl_cxa_refcont: address not found"));
1514 _rtld_error("No shared object contains address"); 1514 _rtld_error("No shared object contains address");
1515 _rtld_exclusive_exit(&mask); 1515 _rtld_exclusive_exit(&mask);
1516 return; 1516 return;
1517 } 1517 }
1518 if (delta > 0 && obj->cxa_refcount > SIZE_MAX - delta) 1518 if (delta > 0 && obj->cxa_refcount > SIZE_MAX - delta)
1519 _rtld_error("Reference count overflow"); 1519 _rtld_error("Reference count overflow");
1520 else if (delta < 0 && obj->cxa_refcount < -1 + (size_t)-(delta + 1)) 1520 else if (delta < 0 && obj->cxa_refcount < -1 + (size_t)-(delta + 1))
1521 _rtld_error("Reference count underflow"); 1521 _rtld_error("Reference count underflow");
1522 else { 1522 else {
1523 if (obj->cxa_refcount == 0) 1523 if (obj->cxa_refcount == 0)
1524 ++obj->refcount; 1524 ++obj->refcount;
1525 obj->cxa_refcount += delta; 1525 obj->cxa_refcount += delta;
1526 dbg(("new reference count: %zu", obj->cxa_refcount)); 1526 dbg(("new reference count: %zu", obj->cxa_refcount));
1527 if (obj->cxa_refcount == 0) { 1527 if (obj->cxa_refcount == 0) {
1528 --obj->refcount; 1528 --obj->refcount;
1529 if (obj->refcount == 0) 1529 if (obj->refcount == 0)
1530 _rtld_unload_object(&mask, obj, true); 1530 _rtld_unload_object(&mask, obj, true);
1531 } 1531 }
1532 } 1532 }
1533 1533
1534 _rtld_exclusive_exit(&mask); 1534 _rtld_exclusive_exit(&mask);
1535} 1535}
1536 1536
1537pid_t __fork(void); 1537pid_t __fork(void);
1538 1538
1539__dso_public pid_t 1539__dso_public pid_t
1540__locked_fork(int *my_errno) 1540__locked_fork(int *my_errno)
1541{ 1541{
1542 sigset_t mask; 1542 sigset_t mask;
1543 pid_t result; 1543 pid_t result;
1544 1544
1545 _rtld_exclusive_enter(&mask); 1545 _rtld_exclusive_enter(&mask);
1546 result = __fork(); 1546 result = __fork();
1547 if (result == -1) 1547 if (result == -1)
1548 *my_errno = errno; 1548 *my_errno = errno;
1549 _rtld_exclusive_exit(&mask); 1549 _rtld_exclusive_exit(&mask);
1550 1550
1551 return result; 1551 return result;
1552} 1552}
1553 1553
1554/* 1554/*
1555 * Error reporting function. Use it like printf. If formats the message 1555 * Error reporting function. Use it like printf. If formats the message
1556 * into a buffer, and sets things up so that the next call to dlerror() 1556 * into a buffer, and sets things up so that the next call to dlerror()
1557 * will return the message. 1557 * will return the message.
1558 */ 1558 */
1559void 1559void
1560_rtld_error(const char *fmt,...) 1560_rtld_error(const char *fmt,...)
1561{ 1561{
1562 static char buf[512]; 1562 static char buf[512];
1563 va_list ap; 1563 va_list ap;
1564 1564
1565 va_start(ap, fmt); 1565 va_start(ap, fmt);
1566 xvsnprintf(buf, sizeof buf, fmt, ap); 1566 xvsnprintf(buf, sizeof buf, fmt, ap);
1567 error_message = buf; 1567 error_message = buf;
1568 va_end(ap); 1568 va_end(ap);
1569} 1569}
1570 1570
1571void 1571void
1572_rtld_debug_state(void) 1572_rtld_debug_state(void)
1573{ 1573{
1574#if defined(__hppa__) 1574#if defined(__hppa__)
1575 __asm volatile("nop" ::: "memory"); 1575 __asm volatile("nop" ::: "memory");
1576#endif 1576#endif
1577 1577
1578 /* Prevent optimizer from removing calls to this function */ 1578 /* Prevent optimizer from removing calls to this function */
1579 __insn_barrier(); 1579 __insn_barrier();
1580} 1580}
1581 1581
1582void 1582void
1583_rtld_linkmap_add(Obj_Entry *obj) 1583_rtld_linkmap_add(Obj_Entry *obj)
1584{ 1584{
1585 struct link_map *l = &obj->linkmap; 1585 struct link_map *l = &obj->linkmap;
1586 struct link_map *prev; 1586 struct link_map *prev;
1587 1587
1588 obj->linkmap.l_name = obj->path; 1588 obj->linkmap.l_name = obj->path;
1589 obj->linkmap.l_addr = obj->relocbase; 1589 obj->linkmap.l_addr = obj->relocbase;
1590 obj->linkmap.l_ld = obj->dynamic; 1590 obj->linkmap.l_ld = obj->dynamic;
1591#ifdef __mips__ 1591#ifdef __mips__
1592 /* XXX This field is not standard and will be removed eventually. */ 1592 /* XXX This field is not standard and will be removed eventually. */
1593 obj->linkmap.l_offs = obj->relocbase; 1593 obj->linkmap.l_offs = obj->relocbase;
1594#endif 1594#endif
1595 1595
1596 if (_rtld_debug.r_map == NULL) { 1596 if (_rtld_debug.r_map == NULL) {
1597 _rtld_debug.r_map = l; 1597 _rtld_debug.r_map = l;
1598 return; 1598 return;
1599 } 1599 }
1600 1600
1601 /* 1601 /*
1602 * Scan to the end of the list, but not past the entry for the 1602 * Scan to the end of the list, but not past the entry for the
1603 * dynamic linker, which we want to keep at the very end. 1603 * dynamic linker, which we want to keep at the very end.
1604 */ 1604 */
1605 for (prev = _rtld_debug.r_map; 1605 for (prev = _rtld_debug.r_map;
1606 prev->l_next != NULL && prev->l_next != &_rtld_objself.linkmap; 1606 prev->l_next != NULL && prev->l_next != &_rtld_objself.linkmap;
1607 prev = prev->l_next); 1607 prev = prev->l_next);
1608 1608
1609 l->l_prev = prev; 1609 l->l_prev = prev;
1610 l->l_next = prev->l_next; 1610 l->l_next = prev->l_next;
1611 if (l->l_next != NULL) 1611 if (l->l_next != NULL)
1612 l->l_next->l_prev = l; 1612 l->l_next->l_prev = l;
1613 prev->l_next = l; 1613 prev->l_next = l;
1614} 1614}
1615 1615
1616void 1616void
1617_rtld_linkmap_delete(Obj_Entry *obj) 1617_rtld_linkmap_delete(Obj_Entry *obj)
1618{ 1618{
1619 struct link_map *l = &obj->linkmap; 1619 struct link_map *l = &obj->linkmap;
1620 1620
1621 if (l->l_prev == NULL) { 1621 if (l->l_prev == NULL) {
1622 if ((_rtld_debug.r_map = l->l_next) != NULL) 1622 if ((_rtld_debug.r_map = l->l_next) != NULL)
1623 l->l_next->l_prev = NULL; 1623 l->l_next->l_prev = NULL;
1624 return; 1624 return;
1625 } 1625 }
1626 if ((l->l_prev->l_next = l->l_next) != NULL) 1626 if ((l->l_prev->l_next = l->l_next) != NULL)
1627 l->l_next->l_prev = l->l_prev; 1627 l->l_next->l_prev = l->l_prev;
1628} 1628}
1629 1629
1630static Obj_Entry * 1630static Obj_Entry *
1631_rtld_obj_from_addr(const void *addr) 1631_rtld_obj_from_addr(const void *addr)
1632{ 1632{
1633 Obj_Entry *obj; 1633 Obj_Entry *obj;
1634 1634
1635 for (obj = _rtld_objlist; obj != NULL; obj = obj->next) { 1635 for (obj = _rtld_objlist; obj != NULL; obj = obj->next) {
1636 if (addr < (void *) obj->mapbase) 1636 if (addr < (void *) obj->mapbase)
1637 continue; 1637 continue;
1638 if (addr < (void *) (obj->mapbase + obj->mapsize)) 1638 if (addr < (void *) (obj->mapbase + obj->mapsize))
1639 return obj; 1639 return obj;
1640 } 1640 }
1641 return NULL; 1641 return NULL;
1642} 1642}
1643 1643
1644static void 1644static void
1645_rtld_objlist_clear(Objlist *list) 1645_rtld_objlist_clear(Objlist *list)
1646{ 1646{
1647 while (!SIMPLEQ_EMPTY(list)) { 1647 while (!SIMPLEQ_EMPTY(list)) {
1648 Objlist_Entry* elm = SIMPLEQ_FIRST(list); 1648 Objlist_Entry* elm = SIMPLEQ_FIRST(list);
1649 SIMPLEQ_REMOVE_HEAD(list, link); 1649 SIMPLEQ_REMOVE_HEAD(list, link);
1650 xfree(elm); 1650 xfree(elm);
1651 } 1651 }
1652} 1652}
1653 1653
1654static void 1654static void
1655_rtld_objlist_remove(Objlist *list, Obj_Entry *obj) 1655_rtld_objlist_remove(Objlist *list, Obj_Entry *obj)
1656{ 1656{
1657 Objlist_Entry *elm; 1657 Objlist_Entry *elm;
1658 1658
1659 if ((elm = _rtld_objlist_find(list, obj)) != NULL) { 1659 if ((elm = _rtld_objlist_find(list, obj)) != NULL) {
1660 SIMPLEQ_REMOVE(list, elm, Struct_Objlist_Entry, link); 1660 SIMPLEQ_REMOVE(list, elm, Struct_Objlist_Entry, link);
1661 xfree(elm); 1661 xfree(elm);
1662 } 1662 }
1663} 1663}
1664 1664
1665#define RTLD_EXCLUSIVE_MASK 0x80000000U 1665#define RTLD_EXCLUSIVE_MASK 0x80000000U
1666static volatile unsigned int _rtld_mutex; 1666static volatile unsigned int _rtld_mutex;
1667static volatile unsigned int _rtld_waiter_exclusive; 1667static volatile unsigned int _rtld_waiter_exclusive;
1668static volatile unsigned int _rtld_waiter_shared; 1668static volatile unsigned int _rtld_waiter_shared;
1669 1669
1670void 1670void
1671_rtld_shared_enter(void) 1671_rtld_shared_enter(void)
1672{ 1672{
1673 unsigned int cur; 1673 unsigned int cur;
1674 lwpid_t waiter, self = 0; 1674 lwpid_t waiter, self = 0;
1675 1675
1676 membar_enter(); 1676 membar_enter();
1677 1677
1678 for (;;) { 1678 for (;;) {
1679 cur = _rtld_mutex; 1679 cur = _rtld_mutex;
1680 /* 1680 /*
1681 * First check if we are currently not exclusively locked. 1681 * First check if we are currently not exclusively locked.
1682 */ 1682 */
1683 if ((cur & RTLD_EXCLUSIVE_MASK) == 0) { 1683 if ((cur & RTLD_EXCLUSIVE_MASK) == 0) {
1684 /* Yes, so increment use counter */ 1684 /* Yes, so increment use counter */
1685 if (atomic_cas_uint(&_rtld_mutex, cur, cur + 1) != cur) 1685 if (atomic_cas_uint(&_rtld_mutex, cur, cur + 1) != cur)
1686 continue; 1686 continue;
1687 membar_enter(); 1687 membar_enter();
1688 return; 1688 return;
1689 } 1689 }
1690 /* 1690 /*
1691 * Someone has an exclusive lock. Puts us on the waiter list. 1691 * Someone has an exclusive lock. Puts us on the waiter list.
1692 */ 1692 */
1693 if (!self) 1693 if (!self)
1694 self = _lwp_self(); 1694 self = _lwp_self();
1695 if (cur == (self | RTLD_EXCLUSIVE_MASK)) { 1695 if (cur == (self | RTLD_EXCLUSIVE_MASK)) {
1696 if (_rtld_mutex_may_recurse) 1696 if (_rtld_mutex_may_recurse)
1697 return; 1697 return;
1698 _rtld_error("%s: dead lock detected", __func__); 1698 _rtld_error("%s: dead lock detected", __func__);
1699 _rtld_die(); 1699 _rtld_die();
1700 } 1700 }
1701 waiter = atomic_swap_uint(&_rtld_waiter_shared, self); 1701 waiter = atomic_swap_uint(&_rtld_waiter_shared, self);
1702 /* 1702 /*
1703 * Check for race against _rtld_exclusive_exit before sleeping. 1703 * Check for race against _rtld_exclusive_exit before sleeping.
1704 */ 1704 */
1705 membar_sync(); 1705 membar_sync();
1706 if ((_rtld_mutex & RTLD_EXCLUSIVE_MASK) || 1706 if ((_rtld_mutex & RTLD_EXCLUSIVE_MASK) ||
1707 _rtld_waiter_exclusive) 1707 _rtld_waiter_exclusive)
1708 _lwp_park(CLOCK_REALTIME, 0, NULL, 0, 1708 _lwp_park(CLOCK_REALTIME, 0, NULL, 0,
1709 __UNVOLATILE(&_rtld_mutex), NULL); 1709 __UNVOLATILE(&_rtld_mutex), NULL);
1710 /* Try to remove us from the waiter list. */ 1710 /* Try to remove us from the waiter list. */
1711 atomic_cas_uint(&_rtld_waiter_shared, self, 0); 1711 atomic_cas_uint(&_rtld_waiter_shared, self, 0);
1712 if (waiter) 1712 if (waiter)
1713 _lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex)); 1713 _lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex));
1714 } 1714 }
1715} 1715}
1716 1716
1717void 1717void
1718_rtld_shared_exit(void) 1718_rtld_shared_exit(void)
1719{ 1719{
1720 lwpid_t waiter; 1720 lwpid_t waiter;
1721 1721
1722 /* 1722 /*
1723 * Shared lock taken after an exclusive lock. 1723 * Shared lock taken after an exclusive lock.
1724 * Just assume this is a partial recursion. 1724 * Just assume this is a partial recursion.
1725 */ 1725 */
1726 if (_rtld_mutex & RTLD_EXCLUSIVE_MASK) 1726 if (_rtld_mutex & RTLD_EXCLUSIVE_MASK)
1727 return; 1727 return;
1728 1728
1729 /* 1729 /*
1730 * Wakeup LWPs waiting for an exclusive lock if this is the last 1730 * Wakeup LWPs waiting for an exclusive lock if this is the last
1731 * LWP on the shared lock. 1731 * LWP on the shared lock.
1732 */ 1732 */
1733 membar_exit(); 1733 membar_exit();
1734 if (atomic_dec_uint_nv(&_rtld_mutex)) 1734 if (atomic_dec_uint_nv(&_rtld_mutex))
1735 return; 1735 return;
1736 membar_sync(); 1736 membar_sync();
1737 if ((waiter = _rtld_waiter_exclusive) != 0) 1737 if ((waiter = _rtld_waiter_exclusive) != 0)
1738 _lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex)); 1738 _lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex));
1739} 1739}
1740 1740
1741void 1741void
1742_rtld_exclusive_enter(sigset_t *mask) 1742_rtld_exclusive_enter(sigset_t *mask)
1743{ 1743{
1744 lwpid_t waiter, self = _lwp_self(); 1744 lwpid_t waiter, self = _lwp_self();
1745 unsigned int locked_value = (unsigned int)self | RTLD_EXCLUSIVE_MASK; 1745 unsigned int locked_value = (unsigned int)self | RTLD_EXCLUSIVE_MASK;
1746 unsigned int cur; 1746 unsigned int cur;
1747 sigset_t blockmask; 1747 sigset_t blockmask;
1748 1748
1749 sigfillset(&blockmask); 1749 sigfillset(&blockmask);
1750 sigdelset(&blockmask, SIGTRAP); /* Allow the debugger */ 1750 sigdelset(&blockmask, SIGTRAP); /* Allow the debugger */
1751 sigprocmask(SIG_BLOCK, &blockmask, mask); 1751 sigprocmask(SIG_BLOCK, &blockmask, mask);
1752 1752
1753 for (;;) { 1753 for (;;) {
1754 if (atomic_cas_uint(&_rtld_mutex, 0, locked_value) == 0) { 1754 if (atomic_cas_uint(&_rtld_mutex, 0, locked_value) == 0) {
1755 membar_enter(); 1755 membar_enter();
1756 break; 1756 break;
1757 } 1757 }
1758 waiter = atomic_swap_uint(&_rtld_waiter_exclusive, self); 1758 waiter = atomic_swap_uint(&_rtld_waiter_exclusive, self);
1759 membar_sync(); 1759 membar_sync();
1760 cur = _rtld_mutex; 1760 cur = _rtld_mutex;
1761 if (cur == locked_value) { 1761 if (cur == locked_value) {
1762 _rtld_error("%s: dead lock detected", __func__); 1762 _rtld_error("%s: dead lock detected", __func__);
1763 _rtld_die(); 1763 _rtld_die();
1764 } 1764 }
1765 if (cur) 1765 if (cur)
1766 _lwp_park(CLOCK_REALTIME, 0, NULL, 0, 1766 _lwp_park(CLOCK_REALTIME, 0, NULL, 0,
1767 __UNVOLATILE(&_rtld_mutex), NULL); 1767 __UNVOLATILE(&_rtld_mutex), NULL);
1768 atomic_cas_uint(&_rtld_waiter_exclusive, self, 0); 1768 atomic_cas_uint(&_rtld_waiter_exclusive, self, 0);
1769 if (waiter) 1769 if (waiter)
1770 _lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex)); 1770 _lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex));
1771 } 1771 }
1772} 1772}
1773 1773
1774void 1774void
1775_rtld_exclusive_exit(sigset_t *mask) 1775_rtld_exclusive_exit(sigset_t *mask)
1776{ 1776{
1777 lwpid_t waiter; 1777 lwpid_t waiter;
1778 1778
1779 membar_exit(); 1779 membar_exit();
1780 _rtld_mutex = 0; 1780 _rtld_mutex = 0;
1781 membar_sync(); 1781 membar_sync();
1782 if ((waiter = _rtld_waiter_exclusive) != 0) 1782 if ((waiter = _rtld_waiter_exclusive) != 0)
1783 _lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex)); 1783 _lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex));
1784 1784
1785 if ((waiter = _rtld_waiter_shared) != 0) 1785 if ((waiter = _rtld_waiter_shared) != 0)
1786 _lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex)); 1786 _lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex));
1787 1787
1788 sigprocmask(SIG_SETMASK, mask, NULL); 1788 sigprocmask(SIG_SETMASK, mask, NULL);
1789} 1789}
1790 1790
1791int 1791int
1792_rtld_relro(const Obj_Entry *obj, bool wantmain) 1792_rtld_relro(const Obj_Entry *obj, bool wantmain)
1793{ 1793{
1794#ifdef GNU_RELRO 1794#ifdef GNU_RELRO
1795 /* 1795 /*
1796 * If our VM page size is larger than the page size used by the 1796 * If our VM page size is larger than the page size used by the
1797 * linker when laying out the object, we could end up making data 1797 * linker when laying out the object, we could end up making data
1798 * read-only that is unintended. Detect and avoid this situation. 1798 * read-only that is unintended. Detect and avoid this situation.
1799 * It may mean we are unable to protect everything we'd like, but 1799 * It may mean we are unable to protect everything we'd like, but
1800 * it's better than crashing. 1800 * it's better than crashing.
1801 */ 1801 */
1802 uintptr_t relro_end = (uintptr_t)obj->relro_page + obj->relro_size; 1802 uintptr_t relro_end = (uintptr_t)obj->relro_page + obj->relro_size;
1803 uintptr_t relro_start = round_down((uintptr_t)obj->relro_page); 1803 uintptr_t relro_start = round_down((uintptr_t)obj->relro_page);
1804 assert(relro_end >= relro_start); 1804 assert(relro_end >= relro_start);
1805 size_t relro_size = round_down(relro_end) - relro_start; 1805 size_t relro_size = round_down(relro_end) - relro_start;
1806 1806
1807 if (relro_size == 0) 1807 if (relro_size == 0)
1808 return 0; 1808 return 0;
1809 if (wantmain != (obj ==_rtld_objmain)) 1809 if (wantmain != (obj ==_rtld_objmain))
1810 return 0; 1810 return 0;
1811 1811
1812 dbg(("RELRO %s %p %zx\n", obj->path, (void *)relro_start, relro_size)); 1812 dbg(("RELRO %s %p %zx\n", obj->path, (void *)relro_start, relro_size));
1813 if (mprotect((void *)relro_start, relro_size, PROT_READ) == -1) { 1813 if (mprotect((void *)relro_start, relro_size, PROT_READ) == -1) {
1814 _rtld_error("%s: Cannot enforce relro " "protection: %s", 1814 _rtld_error("%s: Cannot enforce relro " "protection: %s",
1815 obj->path, xstrerror(errno)); 1815 obj->path, xstrerror(errno));
1816 return -1; 1816 return -1;
1817 } 1817 }
1818#endif 1818#endif
1819 return 0; 1819 return 0;
1820} 1820}