Sat Oct 4 09:37:12 2008 UTC ()
lib/39649: dlsym(3) does not follow dependencies

Pull across code from FreeBSD to do a search of the passed object and it's
NEEDED objects (dependencies).

Reviewed by gimpy.


(skrll)
diff -r1.121 -r1.122 src/libexec/ld.elf_so/rtld.c
diff -r1.78 -r1.79 src/libexec/ld.elf_so/rtld.h
diff -r1.46 -r1.47 src/libexec/ld.elf_so/symbol.c

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

--- src/libexec/ld.elf_so/rtld.c 2008/09/27 03:52:05 1.121
+++ src/libexec/ld.elf_so/rtld.c 2008/10/04 09:37:12 1.122
@@ -1,1086 +1,1088 @@ @@ -1,1086 +1,1088 @@
1/* $NetBSD: rtld.c,v 1.121 2008/09/27 03:52:05 macallan Exp $ */ 1/* $NetBSD: rtld.c,v 1.122 2008/10/04 09:37:12 skrll 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.121 2008/09/27 03:52:05 macallan Exp $"); 43__RCSID("$NetBSD: rtld.c,v 1.122 2008/10/04 09:37:12 skrll Exp $");
44#endif /* not lint */ 44#endif /* not lint */
45 45
46#include <err.h> 46#include <err.h>
47#include <errno.h> 47#include <errno.h>
48#include <fcntl.h> 48#include <fcntl.h>
49#include <stdarg.h> 49#include <stdarg.h>
50#include <stdio.h> 50#include <stdio.h>
51#include <stdlib.h> 51#include <stdlib.h>
52#include <string.h> 52#include <string.h>
53#include <unistd.h> 53#include <unistd.h>
54#include <sys/param.h> 54#include <sys/param.h>
55#include <sys/mman.h> 55#include <sys/mman.h>
56#include <dirent.h> 56#include <dirent.h>
57 57
58#include <ctype.h> 58#include <ctype.h>
59 59
60#include <dlfcn.h> 60#include <dlfcn.h>
61#include "debug.h" 61#include "debug.h"
62#include "rtld.h" 62#include "rtld.h"
63 63
64#if !defined(lint) 64#if !defined(lint)
65#include "sysident.h" 65#include "sysident.h"
66#endif 66#endif
67 67
68/* 68/*
69 * Function declarations. 69 * Function declarations.
70 */ 70 */
71static void _rtld_init(caddr_t, caddr_t, const char *); 71static void _rtld_init(caddr_t, caddr_t, const char *);
72static void _rtld_exit(void); 72static void _rtld_exit(void);
73 73
74Elf_Addr _rtld(Elf_Addr *, Elf_Addr); 74Elf_Addr _rtld(Elf_Addr *, Elf_Addr);
75 75
76 76
77/* 77/*
78 * Data declarations. 78 * Data declarations.
79 */ 79 */
80static char *error_message; /* Message for dlopen(), or NULL */ 80static char *error_message; /* Message for dlopen(), or NULL */
81 81
82struct r_debug _rtld_debug; /* for GDB; */ 82struct r_debug _rtld_debug; /* for GDB; */
83bool _rtld_trust; /* False for setuid and setgid programs */ 83bool _rtld_trust; /* False for setuid and setgid programs */
84Obj_Entry *_rtld_objlist; /* Head of linked list of shared objects */ 84Obj_Entry *_rtld_objlist; /* Head of linked list of shared objects */
85Obj_Entry **_rtld_objtail; /* Link field of last object in list */ 85Obj_Entry **_rtld_objtail; /* Link field of last object in list */
86Obj_Entry *_rtld_objmain; /* The main program shared object */ 86Obj_Entry *_rtld_objmain; /* The main program shared object */
87Obj_Entry _rtld_objself; /* The dynamic linker shared object */ 87Obj_Entry _rtld_objself; /* The dynamic linker shared object */
88const char _rtld_path[] = _PATH_RTLD; 88const char _rtld_path[] = _PATH_RTLD;
89 89
90/* Initialize a fake symbol for resolving undefined weak references. */ 90/* Initialize a fake symbol for resolving undefined weak references. */
91Elf_Sym _rtld_sym_zero = { 91Elf_Sym _rtld_sym_zero = {
92 .st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE), 92 .st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
93 .st_shndx = SHN_ABS, 93 .st_shndx = SHN_ABS,
94}; 94};
95int _rtld_pagesz; /* Page size, as provided by kernel */ 95int _rtld_pagesz; /* Page size, as provided by kernel */
96 96
97Search_Path *_rtld_default_paths; 97Search_Path *_rtld_default_paths;
98Search_Path *_rtld_paths; 98Search_Path *_rtld_paths;
99 99
100Library_Xform *_rtld_xforms; 100Library_Xform *_rtld_xforms;
101 101
102/* 102/*
103 * Global declarations normally provided by crt0. 103 * Global declarations normally provided by crt0.
104 */ 104 */
105char *__progname; 105char *__progname;
106char **environ; 106char **environ;
107 107
108#if defined(RTLD_DEBUG) 108#if defined(RTLD_DEBUG)
109#ifndef __sh__ 109#ifndef __sh__
110extern Elf_Addr _GLOBAL_OFFSET_TABLE_[]; 110extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
111#else /* 32-bit SuperH */ 111#else /* 32-bit SuperH */
112register Elf_Addr *_GLOBAL_OFFSET_TABLE_ asm("r12"); 112register Elf_Addr *_GLOBAL_OFFSET_TABLE_ asm("r12");
113#endif 113#endif
114#endif /* RTLD_DEBUG */ 114#endif /* RTLD_DEBUG */
115extern Elf_Dyn _DYNAMIC; 115extern Elf_Dyn _DYNAMIC;
116 116
117static void _rtld_call_fini_functions(int); 117static void _rtld_call_fini_functions(int);
118static void _rtld_call_init_functions(void); 118static void _rtld_call_init_functions(void);
119static void _rtld_initlist_visit(Objlist *, Obj_Entry *, int); 119static void _rtld_initlist_visit(Objlist *, Obj_Entry *, int);
120static void _rtld_initlist_tsort(Objlist *, int); 120static void _rtld_initlist_tsort(Objlist *, int);
121static Obj_Entry *_rtld_dlcheck(void *); 121static Obj_Entry *_rtld_dlcheck(void *);
122static void _rtld_init_dag(Obj_Entry *); 122static void _rtld_init_dag(Obj_Entry *);
123static void _rtld_init_dag1(Obj_Entry *, Obj_Entry *); 123static void _rtld_init_dag1(Obj_Entry *, Obj_Entry *);
124static void _rtld_objlist_remove(Objlist *, Obj_Entry *); 124static void _rtld_objlist_remove(Objlist *, Obj_Entry *);
125static void _rtld_objlist_clear(Objlist *); 125static void _rtld_objlist_clear(Objlist *);
126static void _rtld_unload_object(Obj_Entry *, bool); 126static void _rtld_unload_object(Obj_Entry *, bool);
127static void _rtld_unref_dag(Obj_Entry *); 127static void _rtld_unref_dag(Obj_Entry *);
128static Obj_Entry *_rtld_obj_from_addr(const void *); 128static Obj_Entry *_rtld_obj_from_addr(const void *);
129 129
130static void 130static void
131_rtld_call_fini_functions(int force) 131_rtld_call_fini_functions(int force)
132{ 132{
133 Objlist_Entry *elm; 133 Objlist_Entry *elm;
134 Objlist finilist; 134 Objlist finilist;
135 Obj_Entry *obj; 135 Obj_Entry *obj;
136 136
137 dbg(("_rtld_call_fini_functions(%d)", force)); 137 dbg(("_rtld_call_fini_functions(%d)", force));
138 138
139 SIMPLEQ_INIT(&finilist); 139 SIMPLEQ_INIT(&finilist);
140 _rtld_initlist_tsort(&finilist, 1); 140 _rtld_initlist_tsort(&finilist, 1);
141 141
142 /* First pass: objects _not_ marked with DF_1_INITFIRST. */ 142 /* First pass: objects _not_ marked with DF_1_INITFIRST. */
143 SIMPLEQ_FOREACH(elm, &finilist, link) { 143 SIMPLEQ_FOREACH(elm, &finilist, link) {
144 obj = elm->obj; 144 obj = elm->obj;
145 if (obj->refcount > 0 && !force) { 145 if (obj->refcount > 0 && !force) {
146 continue; 146 continue;
147 } 147 }
148 if (obj->fini == NULL || obj->fini_called || obj->initfirst) { 148 if (obj->fini == NULL || obj->fini_called || obj->initfirst) {
149 continue; 149 continue;
150 } 150 }
151 dbg (("calling fini function %s at %p", obj->path, 151 dbg (("calling fini function %s at %p", obj->path,
152 (void *)obj->fini)); 152 (void *)obj->fini));
153 obj->fini_called = 1; 153 obj->fini_called = 1;
154 (*obj->fini)(); 154 (*obj->fini)();
155 } 155 }
156 156
157 /* Second pass: objects marked with DF_1_INITFIRST. */ 157 /* Second pass: objects marked with DF_1_INITFIRST. */
158 SIMPLEQ_FOREACH(elm, &finilist, link) { 158 SIMPLEQ_FOREACH(elm, &finilist, link) {
159 obj = elm->obj; 159 obj = elm->obj;
160 if (obj->refcount > 0 && !force) { 160 if (obj->refcount > 0 && !force) {
161 continue; 161 continue;
162 } 162 }
163 if (obj->fini == NULL || obj->fini_called) { 163 if (obj->fini == NULL || obj->fini_called) {
164 continue; 164 continue;
165 } 165 }
166 dbg (("calling fini function %s at %p (DF_1_INITFIRST)", 166 dbg (("calling fini function %s at %p (DF_1_INITFIRST)",
167 obj->path, (void *)obj->fini)); 167 obj->path, (void *)obj->fini));
168 obj->fini_called = 1; 168 obj->fini_called = 1;
169 (*obj->fini)(); 169 (*obj->fini)();
170 } 170 }
171 171
172 _rtld_objlist_clear(&finilist); 172 _rtld_objlist_clear(&finilist);
173} 173}
174 174
175static void 175static void
176_rtld_call_init_functions() 176_rtld_call_init_functions()
177{ 177{
178 Objlist_Entry *elm; 178 Objlist_Entry *elm;
179 Objlist initlist; 179 Objlist initlist;
180 Obj_Entry *obj; 180 Obj_Entry *obj;
181 181
182 dbg(("_rtld_call_init_functions()")); 182 dbg(("_rtld_call_init_functions()"));
183 SIMPLEQ_INIT(&initlist); 183 SIMPLEQ_INIT(&initlist);
184 _rtld_initlist_tsort(&initlist, 0); 184 _rtld_initlist_tsort(&initlist, 0);
185 185
186 /* First pass: objects marked with DF_1_INITFIRST. */ 186 /* First pass: objects marked with DF_1_INITFIRST. */
187 SIMPLEQ_FOREACH(elm, &initlist, link) { 187 SIMPLEQ_FOREACH(elm, &initlist, link) {
188 obj = elm->obj; 188 obj = elm->obj;
189 if (obj->init == NULL || obj->init_called || !obj->initfirst) { 189 if (obj->init == NULL || obj->init_called || !obj->initfirst) {
190 continue; 190 continue;
191 } 191 }
192 dbg (("calling init function %s at %p (DF_1_INITFIRST)", 192 dbg (("calling init function %s at %p (DF_1_INITFIRST)",
193 obj->path, (void *)obj->init)); 193 obj->path, (void *)obj->init));
194 obj->init_called = 1; 194 obj->init_called = 1;
195 (*obj->init)(); 195 (*obj->init)();
196 } 196 }
197 197
198 /* Second pass: all other objects. */ 198 /* Second pass: all other objects. */
199 SIMPLEQ_FOREACH(elm, &initlist, link) { 199 SIMPLEQ_FOREACH(elm, &initlist, link) {
200 obj = elm->obj; 200 obj = elm->obj;
201 if (obj->init == NULL || obj->init_called) { 201 if (obj->init == NULL || obj->init_called) {
202 continue; 202 continue;
203 } 203 }
204 dbg (("calling init function %s at %p", obj->path, 204 dbg (("calling init function %s at %p", obj->path,
205 (void *)obj->init)); 205 (void *)obj->init));
206 obj->init_called = 1; 206 obj->init_called = 1;
207 (*obj->init)(); 207 (*obj->init)();
208 } 208 }
209 209
210 _rtld_objlist_clear(&initlist); 210 _rtld_objlist_clear(&initlist);
211} 211}
212 212
213/* 213/*
214 * Initialize the dynamic linker. The argument is the address at which 214 * Initialize the dynamic linker. The argument is the address at which
215 * the dynamic linker has been mapped into memory. The primary task of 215 * the dynamic linker has been mapped into memory. The primary task of
216 * this function is to create an Obj_Entry for the dynamic linker and 216 * this function is to create an Obj_Entry for the dynamic linker and
217 * to resolve the PLT relocation for platforms that need it (those that 217 * to resolve the PLT relocation for platforms that need it (those that
218 * define __HAVE_FUNCTION_DESCRIPTORS 218 * define __HAVE_FUNCTION_DESCRIPTORS
219 */ 219 */
220static void 220static void
221_rtld_init(caddr_t mapbase, caddr_t relocbase, const char *execname) 221_rtld_init(caddr_t mapbase, caddr_t relocbase, const char *execname)
222{ 222{
223 223
224 /* Conjure up an Obj_Entry structure for the dynamic linker. */ 224 /* Conjure up an Obj_Entry structure for the dynamic linker. */
225 _rtld_objself.path = __UNCONST(_rtld_path); 225 _rtld_objself.path = __UNCONST(_rtld_path);
226 _rtld_objself.pathlen = sizeof(_rtld_path)-1; 226 _rtld_objself.pathlen = sizeof(_rtld_path)-1;
227 _rtld_objself.rtld = true; 227 _rtld_objself.rtld = true;
228 _rtld_objself.mapbase = mapbase; 228 _rtld_objself.mapbase = mapbase;
229 _rtld_objself.relocbase = relocbase; 229 _rtld_objself.relocbase = relocbase;
230 _rtld_objself.dynamic = (Elf_Dyn *) &_DYNAMIC; 230 _rtld_objself.dynamic = (Elf_Dyn *) &_DYNAMIC;
231 _rtld_objself.strtab = "_rtld_sym_zero"; 231 _rtld_objself.strtab = "_rtld_sym_zero";
232 232
233 /* 233 /*
234 * Set value to -relocabase so that 234 * Set value to -relocabase so that
235 * _rtld_objself.relocbase + _rtld_smy_zero.st_value == 0 235 * _rtld_objself.relocbase + _rtld_smy_zero.st_value == 0
236 * This allows unresolved references to weak symbols to be computed 236 * This allows unresolved references to weak symbols to be computed
237 * to value a value of 0. 237 * to value a value of 0.
238 */ 238 */
239 _rtld_sym_zero.st_value = -(uintptr_t)relocbase; 239 _rtld_sym_zero.st_value = -(uintptr_t)relocbase;
240 240
241 _rtld_digest_dynamic(_rtld_path, &_rtld_objself); 241 _rtld_digest_dynamic(_rtld_path, &_rtld_objself);
242 assert(!_rtld_objself.needed); 242 assert(!_rtld_objself.needed);
243#if !defined(__hppa__) 243#if !defined(__hppa__)
244 assert(!_rtld_objself.pltrel && !_rtld_objself.pltrela); 244 assert(!_rtld_objself.pltrel && !_rtld_objself.pltrela);
245#else 245#else
246 _rtld_relocate_plt_objects(&_rtld_objself); 246 _rtld_relocate_plt_objects(&_rtld_objself);
247#endif 247#endif
248#if !defined(__mips__) && !defined(__hppa__) 248#if !defined(__mips__) && !defined(__hppa__)
249 assert(!_rtld_objself.pltgot); 249 assert(!_rtld_objself.pltgot);
250#endif 250#endif
251#if !defined(__arm__) && !defined(__mips__) && !defined(__sh__) 251#if !defined(__arm__) && !defined(__mips__) && !defined(__sh__)
252 /* ARM, MIPS and SH{3,5} have a bogus DT_TEXTREL. */ 252 /* ARM, MIPS and SH{3,5} have a bogus DT_TEXTREL. */
253 assert(!_rtld_objself.textrel); 253 assert(!_rtld_objself.textrel);
254#endif 254#endif
255 255
256 _rtld_add_paths(execname, &_rtld_default_paths, 256 _rtld_add_paths(execname, &_rtld_default_paths,
257 RTLD_DEFAULT_LIBRARY_PATH); 257 RTLD_DEFAULT_LIBRARY_PATH);
258 258
259 /* 259 /*
260 * Set up the _rtld_objlist pointer, so that rtld symbols can be found. 260 * Set up the _rtld_objlist pointer, so that rtld symbols can be found.
261 */ 261 */
262 _rtld_objlist = &_rtld_objself; 262 _rtld_objlist = &_rtld_objself;
263 263
264 /* Make the object list empty again. */ 264 /* Make the object list empty again. */
265 _rtld_objlist = NULL; 265 _rtld_objlist = NULL;
266 _rtld_objtail = &_rtld_objlist; 266 _rtld_objtail = &_rtld_objlist;
267 267
268 _rtld_debug.r_brk = _rtld_debug_state; 268 _rtld_debug.r_brk = _rtld_debug_state;
269 _rtld_debug.r_state = RT_CONSISTENT; 269 _rtld_debug.r_state = RT_CONSISTENT;
270} 270}
271 271
272/* 272/*
273 * Cleanup procedure. It will be called (by the atexit() mechanism) just 273 * Cleanup procedure. It will be called (by the atexit() mechanism) just
274 * before the process exits. 274 * before the process exits.
275 */ 275 */
276static void 276static void
277_rtld_exit(void) 277_rtld_exit(void)
278{ 278{
279 dbg(("rtld_exit()")); 279 dbg(("rtld_exit()"));
280 280
281 _rtld_call_fini_functions(1); 281 _rtld_call_fini_functions(1);
282} 282}
283 283
284/* 284/*
285 * Main entry point for dynamic linking. The argument is the stack 285 * Main entry point for dynamic linking. The argument is the stack
286 * pointer. The stack is expected to be laid out as described in the 286 * pointer. The stack is expected to be laid out as described in the
287 * SVR4 ABI specification, Intel 386 Processor Supplement. Specifically, 287 * SVR4 ABI specification, Intel 386 Processor Supplement. Specifically,
288 * the stack pointer points to a word containing ARGC. Following that 288 * the stack pointer points to a word containing ARGC. Following that
289 * in the stack is a null-terminated sequence of pointers to argument 289 * in the stack is a null-terminated sequence of pointers to argument
290 * strings. Then comes a null-terminated sequence of pointers to 290 * strings. Then comes a null-terminated sequence of pointers to
291 * environment strings. Finally, there is a sequence of "auxiliary 291 * environment strings. Finally, there is a sequence of "auxiliary
292 * vector" entries. 292 * vector" entries.
293 * 293 *
294 * This function returns the entry point for the main program, the dynamic 294 * This function returns the entry point for the main program, the dynamic
295 * linker's exit procedure in sp[0], and a pointer to the main object in 295 * linker's exit procedure in sp[0], and a pointer to the main object in
296 * sp[1]. 296 * sp[1].
297 */ 297 */
298Elf_Addr 298Elf_Addr
299_rtld(Elf_Addr *sp, Elf_Addr relocbase) 299_rtld(Elf_Addr *sp, Elf_Addr relocbase)
300{ 300{
301 const AuxInfo *pAUX_base, *pAUX_entry, *pAUX_execfd, *pAUX_phdr, 301 const AuxInfo *pAUX_base, *pAUX_entry, *pAUX_execfd, *pAUX_phdr,
302 *pAUX_phent, *pAUX_phnum, *pAUX_euid, *pAUX_egid, 302 *pAUX_phent, *pAUX_phnum, *pAUX_euid, *pAUX_egid,
303 *pAUX_ruid, *pAUX_rgid; 303 *pAUX_ruid, *pAUX_rgid;
304 const AuxInfo *pAUX_pagesz; 304 const AuxInfo *pAUX_pagesz;
305 char **env; 305 char **env;
306 const AuxInfo *aux; 306 const AuxInfo *aux;
307 const AuxInfo *auxp; 307 const AuxInfo *auxp;
308 Elf_Addr *const osp = sp; 308 Elf_Addr *const osp = sp;
309 bool bind_now = 0; 309 bool bind_now = 0;
310 const char *ld_bind_now; 310 const char *ld_bind_now;
311 const char **argv; 311 const char **argv;
312 const char *execname; 312 const char *execname;
313 long argc; 313 long argc;
314 const char **real___progname; 314 const char **real___progname;
315 const Obj_Entry **real___mainprog_obj; 315 const Obj_Entry **real___mainprog_obj;
316 char ***real_environ; 316 char ***real_environ;
317#if defined(RTLD_DEBUG) 317#if defined(RTLD_DEBUG)
318 int i = 0; 318 int i = 0;
319#endif 319#endif
320 320
321 /* 321 /*
322 * On entry, the dynamic linker itself has not been relocated yet. 322 * On entry, the dynamic linker itself has not been relocated yet.
323 * Be very careful not to reference any global data until after 323 * Be very careful not to reference any global data until after
324 * _rtld_init has returned. It is OK to reference file-scope statics 324 * _rtld_init has returned. It is OK to reference file-scope statics
325 * and string constants, and to call static and global functions. 325 * and string constants, and to call static and global functions.
326 */ 326 */
327 /* Find the auxiliary vector on the stack. */ 327 /* Find the auxiliary vector on the stack. */
328 /* first Elf_Word reserved to address of exit routine */ 328 /* first Elf_Word reserved to address of exit routine */
329#if defined(RTLD_DEBUG) 329#if defined(RTLD_DEBUG)
330 debug = 1; 330 debug = 1;
331 dbg(("sp = %p, argc = %ld, argv = %p <%s> relocbase %p", sp, 331 dbg(("sp = %p, argc = %ld, argv = %p <%s> relocbase %p", sp,
332 (long)sp[2], &sp[3], (char *) sp[3], (void *)relocbase)); 332 (long)sp[2], &sp[3], (char *) sp[3], (void *)relocbase));
333 dbg(("got is at %p, dynamic is at %p", _GLOBAL_OFFSET_TABLE_, 333 dbg(("got is at %p, dynamic is at %p", _GLOBAL_OFFSET_TABLE_,
334 &_DYNAMIC)); 334 &_DYNAMIC));
335 dbg(("_ctype_ is %p", _ctype_)); 335 dbg(("_ctype_ is %p", _ctype_));
336#endif 336#endif
337 337
338 sp += 2; /* skip over return argument space */ 338 sp += 2; /* skip over return argument space */
339 argv = (const char **) &sp[1]; 339 argv = (const char **) &sp[1];
340 argc = *(long *)sp; 340 argc = *(long *)sp;
341 sp += 2 + argc; /* Skip over argc, arguments, and NULL 341 sp += 2 + argc; /* Skip over argc, arguments, and NULL
342 * terminator */ 342 * terminator */
343 env = (char **) sp; 343 env = (char **) sp;
344 while (*sp++ != 0) { /* Skip over environment, and NULL terminator */ 344 while (*sp++ != 0) { /* Skip over environment, and NULL terminator */
345#if defined(RTLD_DEBUG) 345#if defined(RTLD_DEBUG)
346 dbg(("env[%d] = %p %s", i++, (void *)sp[-1], (char *)sp[-1])); 346 dbg(("env[%d] = %p %s", i++, (void *)sp[-1], (char *)sp[-1]));
347#endif 347#endif
348 } 348 }
349 aux = (const AuxInfo *) sp; 349 aux = (const AuxInfo *) sp;
350 350
351 pAUX_base = pAUX_entry = pAUX_execfd = NULL; 351 pAUX_base = pAUX_entry = pAUX_execfd = NULL;
352 pAUX_phdr = pAUX_phent = pAUX_phnum = NULL; 352 pAUX_phdr = pAUX_phent = pAUX_phnum = NULL;
353 pAUX_euid = pAUX_ruid = pAUX_egid = pAUX_rgid = NULL; 353 pAUX_euid = pAUX_ruid = pAUX_egid = pAUX_rgid = NULL;
354 pAUX_pagesz = NULL; 354 pAUX_pagesz = NULL;
355 355
356 execname = NULL; 356 execname = NULL;
357 357
358 /* Digest the auxiliary vector. */ 358 /* Digest the auxiliary vector. */
359 for (auxp = aux; auxp->a_type != AT_NULL; ++auxp) { 359 for (auxp = aux; auxp->a_type != AT_NULL; ++auxp) {
360 switch (auxp->a_type) { 360 switch (auxp->a_type) {
361 case AT_BASE: 361 case AT_BASE:
362 pAUX_base = auxp; 362 pAUX_base = auxp;
363 break; 363 break;
364 case AT_ENTRY: 364 case AT_ENTRY:
365 pAUX_entry = auxp; 365 pAUX_entry = auxp;
366 break; 366 break;
367 case AT_EXECFD: 367 case AT_EXECFD:
368 pAUX_execfd = auxp; 368 pAUX_execfd = auxp;
369 break; 369 break;
370 case AT_PHDR: 370 case AT_PHDR:
371 pAUX_phdr = auxp; 371 pAUX_phdr = auxp;
372 break; 372 break;
373 case AT_PHENT: 373 case AT_PHENT:
374 pAUX_phent = auxp; 374 pAUX_phent = auxp;
375 break; 375 break;
376 case AT_PHNUM: 376 case AT_PHNUM:
377 pAUX_phnum = auxp; 377 pAUX_phnum = auxp;
378 break; 378 break;
379#ifdef AT_EUID 379#ifdef AT_EUID
380 case AT_EUID: 380 case AT_EUID:
381 pAUX_euid = auxp; 381 pAUX_euid = auxp;
382 break; 382 break;
383 case AT_RUID: 383 case AT_RUID:
384 pAUX_ruid = auxp; 384 pAUX_ruid = auxp;
385 break; 385 break;
386 case AT_EGID: 386 case AT_EGID:
387 pAUX_egid = auxp; 387 pAUX_egid = auxp;
388 break; 388 break;
389 case AT_RGID: 389 case AT_RGID:
390 pAUX_rgid = auxp; 390 pAUX_rgid = auxp;
391 break; 391 break;
392#endif 392#endif
393#ifdef AT_SUN_EXECNAME 393#ifdef AT_SUN_EXECNAME
394 case AT_SUN_EXECNAME: 394 case AT_SUN_EXECNAME:
395 execname = (const char *)(const void *)auxp->a_v; 395 execname = (const char *)(const void *)auxp->a_v;
396 break; 396 break;
397#endif 397#endif
398 case AT_PAGESZ: 398 case AT_PAGESZ:
399 pAUX_pagesz = auxp; 399 pAUX_pagesz = auxp;
400 break; 400 break;
401 } 401 }
402 } 402 }
403 403
404 /* Initialize and relocate ourselves. */ 404 /* Initialize and relocate ourselves. */
405 if (pAUX_base == NULL) { 405 if (pAUX_base == NULL) {
406 _rtld_error("Bad pAUX_base"); 406 _rtld_error("Bad pAUX_base");
407 _rtld_die(); 407 _rtld_die();
408 } 408 }
409 assert(pAUX_pagesz != NULL); 409 assert(pAUX_pagesz != NULL);
410 _rtld_pagesz = (int)pAUX_pagesz->a_v; 410 _rtld_pagesz = (int)pAUX_pagesz->a_v;
411 _rtld_init((caddr_t)pAUX_base->a_v, (caddr_t)relocbase, execname); 411 _rtld_init((caddr_t)pAUX_base->a_v, (caddr_t)relocbase, execname);
412 412
413 __progname = _rtld_objself.path; 413 __progname = _rtld_objself.path;
414 environ = env; 414 environ = env;
415 415
416 _rtld_trust = ((pAUX_euid ? (uid_t)pAUX_euid->a_v : geteuid()) == 416 _rtld_trust = ((pAUX_euid ? (uid_t)pAUX_euid->a_v : geteuid()) ==
417 (pAUX_ruid ? (uid_t)pAUX_ruid->a_v : getuid())) && 417 (pAUX_ruid ? (uid_t)pAUX_ruid->a_v : getuid())) &&
418 ((pAUX_egid ? (gid_t)pAUX_egid->a_v : getegid()) == 418 ((pAUX_egid ? (gid_t)pAUX_egid->a_v : getegid()) ==
419 (pAUX_rgid ? (gid_t)pAUX_rgid->a_v : getgid())); 419 (pAUX_rgid ? (gid_t)pAUX_rgid->a_v : getgid()));
420 420
421 ld_bind_now = getenv("LD_BIND_NOW"); 421 ld_bind_now = getenv("LD_BIND_NOW");
422 if (ld_bind_now != NULL && *ld_bind_now != '\0') 422 if (ld_bind_now != NULL && *ld_bind_now != '\0')
423 bind_now = true; 423 bind_now = true;
424 if (_rtld_trust) { 424 if (_rtld_trust) {
425#ifdef DEBUG 425#ifdef DEBUG
426 const char *ld_debug = getenv("LD_DEBUG"); 426 const char *ld_debug = getenv("LD_DEBUG");
427#ifdef RTLD_DEBUG 427#ifdef RTLD_DEBUG
428 debug = 0; 428 debug = 0;
429#endif 429#endif
430 if (ld_debug != NULL && *ld_debug != '\0') 430 if (ld_debug != NULL && *ld_debug != '\0')
431 debug = 1; 431 debug = 1;
432#endif 432#endif
433 _rtld_add_paths(execname, &_rtld_paths, 433 _rtld_add_paths(execname, &_rtld_paths,
434 getenv("LD_LIBRARY_PATH")); 434 getenv("LD_LIBRARY_PATH"));
435 } else { 435 } else {
436 execname = NULL; 436 execname = NULL;
437 unsetenv("LD_DEBUG"); 437 unsetenv("LD_DEBUG");
438 unsetenv("LD_LIBRARY_PATH"); 438 unsetenv("LD_LIBRARY_PATH");
439 } 439 }
440 _rtld_process_hints(execname, &_rtld_paths, &_rtld_xforms, 440 _rtld_process_hints(execname, &_rtld_paths, &_rtld_xforms,
441 _PATH_LD_HINTS); 441 _PATH_LD_HINTS);
442 dbg(("dynamic linker is initialized, mapbase=%p, relocbase=%p", 442 dbg(("dynamic linker is initialized, mapbase=%p, relocbase=%p",
443 _rtld_objself.mapbase, _rtld_objself.relocbase)); 443 _rtld_objself.mapbase, _rtld_objself.relocbase));
444 444
445 /* 445 /*
446 * Load the main program, or process its program header if it is 446 * Load the main program, or process its program header if it is
447 * already loaded. 447 * already loaded.
448 */ 448 */
449 if (pAUX_execfd != NULL) { /* Load the main program. */ 449 if (pAUX_execfd != NULL) { /* Load the main program. */
450 int fd = pAUX_execfd->a_v; 450 int fd = pAUX_execfd->a_v;
451 const char *obj_name = argv[0] ? argv[0] : "main program"; 451 const char *obj_name = argv[0] ? argv[0] : "main program";
452 dbg(("loading main program")); 452 dbg(("loading main program"));
453 _rtld_objmain = _rtld_map_object(obj_name, fd, NULL); 453 _rtld_objmain = _rtld_map_object(obj_name, fd, NULL);
454 close(fd); 454 close(fd);
455 if (_rtld_objmain == NULL) 455 if (_rtld_objmain == NULL)
456 _rtld_die(); 456 _rtld_die();
457 } else { /* Main program already loaded. */ 457 } else { /* Main program already loaded. */
458 const Elf_Phdr *phdr; 458 const Elf_Phdr *phdr;
459 int phnum; 459 int phnum;
460 caddr_t entry; 460 caddr_t entry;
461 461
462 dbg(("processing main program's program header")); 462 dbg(("processing main program's program header"));
463 assert(pAUX_phdr != NULL); 463 assert(pAUX_phdr != NULL);
464 phdr = (const Elf_Phdr *) pAUX_phdr->a_v; 464 phdr = (const Elf_Phdr *) pAUX_phdr->a_v;
465 assert(pAUX_phnum != NULL); 465 assert(pAUX_phnum != NULL);
466 phnum = pAUX_phnum->a_v; 466 phnum = pAUX_phnum->a_v;
467 assert(pAUX_phent != NULL); 467 assert(pAUX_phent != NULL);
468 assert(pAUX_phent->a_v == sizeof(Elf_Phdr)); 468 assert(pAUX_phent->a_v == sizeof(Elf_Phdr));
469 assert(pAUX_entry != NULL); 469 assert(pAUX_entry != NULL);
470 entry = (caddr_t) pAUX_entry->a_v; 470 entry = (caddr_t) pAUX_entry->a_v;
471 _rtld_objmain = _rtld_digest_phdr(phdr, phnum, entry); 471 _rtld_objmain = _rtld_digest_phdr(phdr, phnum, entry);
472 _rtld_objmain->path = xstrdup(argv[0] ? argv[0] : 472 _rtld_objmain->path = xstrdup(argv[0] ? argv[0] :
473 "main program"); 473 "main program");
474 _rtld_objmain->pathlen = strlen(_rtld_objmain->path); 474 _rtld_objmain->pathlen = strlen(_rtld_objmain->path);
475 } 475 }
476 476
477 _rtld_objmain->mainprog = true; 477 _rtld_objmain->mainprog = true;
478  478
479 /* 479 /*
480 * Get the actual dynamic linker pathname from the executable if 480 * Get the actual dynamic linker pathname from the executable if
481 * possible. (It should always be possible.) That ensures that 481 * possible. (It should always be possible.) That ensures that
482 * gdb will find the right dynamic linker even if a non-standard 482 * gdb will find the right dynamic linker even if a non-standard
483 * one is being used. 483 * one is being used.
484 */ 484 */
485 if (_rtld_objmain->interp != NULL && 485 if (_rtld_objmain->interp != NULL &&
486 strcmp(_rtld_objmain->interp, _rtld_objself.path) != 0) 486 strcmp(_rtld_objmain->interp, _rtld_objself.path) != 0)
487 _rtld_objself.path = xstrdup(_rtld_objmain->interp); 487 _rtld_objself.path = xstrdup(_rtld_objmain->interp);
488 dbg(("actual dynamic linker is %s", _rtld_objself.path)); 488 dbg(("actual dynamic linker is %s", _rtld_objself.path));
489  489
490 _rtld_digest_dynamic(execname, _rtld_objmain); 490 _rtld_digest_dynamic(execname, _rtld_objmain);
491 491
492 /* Link the main program into the list of objects. */ 492 /* Link the main program into the list of objects. */
493 *_rtld_objtail = _rtld_objmain; 493 *_rtld_objtail = _rtld_objmain;
494 _rtld_objtail = &_rtld_objmain->next; 494 _rtld_objtail = &_rtld_objmain->next;
495 495
496 _rtld_linkmap_add(_rtld_objmain); 496 _rtld_linkmap_add(_rtld_objmain);
497 _rtld_linkmap_add(&_rtld_objself); 497 _rtld_linkmap_add(&_rtld_objself);
498 498
499 ++_rtld_objmain->refcount; 499 ++_rtld_objmain->refcount;
500 _rtld_objmain->mainref = 1; 500 _rtld_objmain->mainref = 1;
501 _rtld_objlist_push_tail(&_rtld_list_main, _rtld_objmain); 501 _rtld_objlist_push_tail(&_rtld_list_main, _rtld_objmain);
502 502
503 if (_rtld_trust) { 503 if (_rtld_trust) {
504 /* 504 /*
505 * Pre-load user-specified objects after the main program 505 * Pre-load user-specified objects after the main program
506 * but before any shared object dependencies. 506 * but before any shared object dependencies.
507 */ 507 */
508 dbg(("preloading objects")); 508 dbg(("preloading objects"));
509 if (_rtld_preload(getenv("LD_PRELOAD")) == -1) 509 if (_rtld_preload(getenv("LD_PRELOAD")) == -1)
510 _rtld_die(); 510 _rtld_die();
511 } else 511 } else
512 unsetenv("LD_PRELOAD"); 512 unsetenv("LD_PRELOAD");
513 513
514 dbg(("loading needed objects")); 514 dbg(("loading needed objects"));
515 if (_rtld_load_needed_objects(_rtld_objmain, RTLD_MAIN) == -1) 515 if (_rtld_load_needed_objects(_rtld_objmain, RTLD_MAIN) == -1)
516 _rtld_die(); 516 _rtld_die();
517 517
518 dbg(("relocating objects")); 518 dbg(("relocating objects"));
519 if (_rtld_relocate_objects(_rtld_objmain, bind_now) == -1) 519 if (_rtld_relocate_objects(_rtld_objmain, bind_now) == -1)
520 _rtld_die(); 520 _rtld_die();
521 521
522 dbg(("doing copy relocations")); 522 dbg(("doing copy relocations"));
523 if (_rtld_do_copy_relocations(_rtld_objmain) == -1) 523 if (_rtld_do_copy_relocations(_rtld_objmain) == -1)
524 _rtld_die(); 524 _rtld_die();
525 525
526 /* 526 /*
527 * Set the __progname, environ and, __mainprog_obj before 527 * Set the __progname, environ and, __mainprog_obj before
528 * calling anything that might use them. 528 * calling anything that might use them.
529 */ 529 */
530 real___progname = _rtld_objmain_sym("__progname"); 530 real___progname = _rtld_objmain_sym("__progname");
531 if (real___progname) { 531 if (real___progname) {
532 if (argv[0] != NULL) { 532 if (argv[0] != NULL) {
533 if ((*real___progname = strrchr(argv[0], '/')) == NULL) 533 if ((*real___progname = strrchr(argv[0], '/')) == NULL)
534 (*real___progname) = argv[0]; 534 (*real___progname) = argv[0];
535 else 535 else
536 (*real___progname)++; 536 (*real___progname)++;
537 } else { 537 } else {
538 (*real___progname) = NULL; 538 (*real___progname) = NULL;
539 } 539 }
540 } 540 }
541 real_environ = _rtld_objmain_sym("environ"); 541 real_environ = _rtld_objmain_sym("environ");
542 if (real_environ) 542 if (real_environ)
543 *real_environ = environ; 543 *real_environ = environ;
544 /* 544 /*
545 * Set __mainprog_obj for old binaries. 545 * Set __mainprog_obj for old binaries.
546 */ 546 */
547 real___mainprog_obj = _rtld_objmain_sym("__mainprog_obj"); 547 real___mainprog_obj = _rtld_objmain_sym("__mainprog_obj");
548 if (real___mainprog_obj) 548 if (real___mainprog_obj)
549 *real___mainprog_obj = _rtld_objmain; 549 *real___mainprog_obj = _rtld_objmain;
550 550
551 dbg(("calling _init functions")); 551 dbg(("calling _init functions"));
552 _rtld_call_init_functions(); 552 _rtld_call_init_functions();
553 553
554 dbg(("control at program entry point = %p, obj = %p, exit = %p", 554 dbg(("control at program entry point = %p, obj = %p, exit = %p",
555 _rtld_objmain->entry, _rtld_objmain, _rtld_exit)); 555 _rtld_objmain->entry, _rtld_objmain, _rtld_exit));
556 556
557 /* 557 /*
558 * Return with the entry point and the exit procedure in at the top 558 * Return with the entry point and the exit procedure in at the top
559 * of stack. 559 * of stack.
560 */ 560 */
561 561
562 _rtld_debug_state(); /* say hello to gdb! */ 562 _rtld_debug_state(); /* say hello to gdb! */
563 563
564 ((void **) osp)[0] = _rtld_exit; 564 ((void **) osp)[0] = _rtld_exit;
565 ((void **) osp)[1] = _rtld_objmain; 565 ((void **) osp)[1] = _rtld_objmain;
566 return (Elf_Addr) _rtld_objmain->entry; 566 return (Elf_Addr) _rtld_objmain->entry;
567} 567}
568 568
569void 569void
570_rtld_die(void) 570_rtld_die(void)
571{ 571{
572 const char *msg = dlerror(); 572 const char *msg = dlerror();
573 573
574 if (msg == NULL) 574 if (msg == NULL)
575 msg = "Fatal error"; 575 msg = "Fatal error";
576 xerrx(1, "%s", msg); 576 xerrx(1, "%s", msg);
577} 577}
578 578
579static Obj_Entry * 579static Obj_Entry *
580_rtld_dlcheck(void *handle) 580_rtld_dlcheck(void *handle)
581{ 581{
582 Obj_Entry *obj; 582 Obj_Entry *obj;
583 583
584 for (obj = _rtld_objlist; obj != NULL; obj = obj->next) 584 for (obj = _rtld_objlist; obj != NULL; obj = obj->next)
585 if (obj == (Obj_Entry *) handle) 585 if (obj == (Obj_Entry *) handle)
586 break; 586 break;
587 587
588 if (obj == NULL || obj->dl_refcount == 0) { 588 if (obj == NULL || obj->dl_refcount == 0) {
589 xwarnx("Invalid shared object handle %p", handle); 589 xwarnx("Invalid shared object handle %p", handle);
590 return NULL; 590 return NULL;
591 } 591 }
592 return obj; 592 return obj;
593} 593}
594 594
595static void 595static void
596_rtld_initlist_visit(Objlist* list, Obj_Entry *obj, int rev) 596_rtld_initlist_visit(Objlist* list, Obj_Entry *obj, int rev)
597{ 597{
598 Needed_Entry* elm; 598 Needed_Entry* elm;
599 599
600 /* dbg(("_rtld_initlist_visit(%s)", obj->path)); */ 600 /* dbg(("_rtld_initlist_visit(%s)", obj->path)); */
601 601
602 if (obj->init_done) 602 if (obj->init_done)
603 return; 603 return;
604 obj->init_done = 1; 604 obj->init_done = 1;
605 605
606 for (elm = obj->needed; elm != NULL; elm = elm->next) { 606 for (elm = obj->needed; elm != NULL; elm = elm->next) {
607 if (elm->obj != NULL) { 607 if (elm->obj != NULL) {
608 _rtld_initlist_visit(list, elm->obj, rev); 608 _rtld_initlist_visit(list, elm->obj, rev);
609 } 609 }
610 } 610 }
611 611
612 if (rev) { 612 if (rev) {
613 _rtld_objlist_push_head(list, obj); 613 _rtld_objlist_push_head(list, obj);
614 } else { 614 } else {
615 _rtld_objlist_push_tail(list, obj); 615 _rtld_objlist_push_tail(list, obj);
616 } 616 }
617} 617}
618 618
619static void 619static void
620_rtld_initlist_tsort(Objlist* list, int rev) 620_rtld_initlist_tsort(Objlist* list, int rev)
621{ 621{
622 dbg(("_rtld_initlist_tsort")); 622 dbg(("_rtld_initlist_tsort"));
623 623
624 Obj_Entry* obj; 624 Obj_Entry* obj;
625 625
626 for (obj = _rtld_objlist->next; obj; obj = obj->next) { 626 for (obj = _rtld_objlist->next; obj; obj = obj->next) {
627 obj->init_done = 0; 627 obj->init_done = 0;
628 } 628 }
629 629
630 for (obj = _rtld_objlist->next; obj; obj = obj->next) { 630 for (obj = _rtld_objlist->next; obj; obj = obj->next) {
631 _rtld_initlist_visit(list, obj, rev); 631 _rtld_initlist_visit(list, obj, rev);
632 } 632 }
633} 633}
634 634
635static void 635static void
636_rtld_init_dag(Obj_Entry *root) 636_rtld_init_dag(Obj_Entry *root)
637{ 637{
638 638
639 _rtld_init_dag1(root, root); 639 _rtld_init_dag1(root, root);
640} 640}
641 641
642static void 642static void
643_rtld_init_dag1(Obj_Entry *root, Obj_Entry *obj) 643_rtld_init_dag1(Obj_Entry *root, Obj_Entry *obj)
644{ 644{
645 const Needed_Entry *needed; 645 const Needed_Entry *needed;
646 646
647 if (!obj->mainref) { 647 if (!obj->mainref) {
648 if (_rtld_objlist_find(&obj->dldags, root)) 648 if (_rtld_objlist_find(&obj->dldags, root))
649 return; 649 return;
650 rdbg(("add %p (%s) to %p (%s) DAG", obj, obj->path, root, 650 rdbg(("add %p (%s) to %p (%s) DAG", obj, obj->path, root,
651 root->path)); 651 root->path));
652 _rtld_objlist_push_tail(&obj->dldags, root); 652 _rtld_objlist_push_tail(&obj->dldags, root);
653 _rtld_objlist_push_tail(&root->dagmembers, obj); 653 _rtld_objlist_push_tail(&root->dagmembers, obj);
654 } 654 }
655 for (needed = obj->needed; needed != NULL; needed = needed->next) 655 for (needed = obj->needed; needed != NULL; needed = needed->next)
656 if (needed->obj != NULL) 656 if (needed->obj != NULL)
657 _rtld_init_dag1(root, needed->obj); 657 _rtld_init_dag1(root, needed->obj);
658} 658}
659 659
660/* 660/*
661 * Note, this is called only for objects loaded by dlopen(). 661 * Note, this is called only for objects loaded by dlopen().
662 */ 662 */
663static void 663static void
664_rtld_unload_object(Obj_Entry *root, bool do_fini_funcs) 664_rtld_unload_object(Obj_Entry *root, bool do_fini_funcs)
665{ 665{
666 666
667 _rtld_unref_dag(root); 667 _rtld_unref_dag(root);
668 if (root->refcount == 0) { /* We are finished with some objects. */ 668 if (root->refcount == 0) { /* We are finished with some objects. */
669 Obj_Entry *obj; 669 Obj_Entry *obj;
670 Obj_Entry **linkp; 670 Obj_Entry **linkp;
671 Objlist_Entry *elm; 671 Objlist_Entry *elm;
672 672
673 /* Finalize objects that are about to be unmapped. */ 673 /* Finalize objects that are about to be unmapped. */
674 if (do_fini_funcs) 674 if (do_fini_funcs)
675 _rtld_call_fini_functions(0); 675 _rtld_call_fini_functions(0);
676 676
677 /* Remove the DAG from all objects' DAG lists. */ 677 /* Remove the DAG from all objects' DAG lists. */
678 SIMPLEQ_FOREACH(elm, &root->dagmembers, link) 678 SIMPLEQ_FOREACH(elm, &root->dagmembers, link)
679 _rtld_objlist_remove(&elm->obj->dldags, root); 679 _rtld_objlist_remove(&elm->obj->dldags, root);
680 680
681 /* Remove the DAG from the RTLD_GLOBAL list. */ 681 /* Remove the DAG from the RTLD_GLOBAL list. */
682 if (root->globalref) { 682 if (root->globalref) {
683 root->globalref = 0; 683 root->globalref = 0;
684 _rtld_objlist_remove(&_rtld_list_global, root); 684 _rtld_objlist_remove(&_rtld_list_global, root);
685 } 685 }
686 686
687 /* Unmap all objects that are no longer referenced. */ 687 /* Unmap all objects that are no longer referenced. */
688 linkp = &_rtld_objlist->next; 688 linkp = &_rtld_objlist->next;
689 while ((obj = *linkp) != NULL) { 689 while ((obj = *linkp) != NULL) {
690 if (obj->refcount == 0) { 690 if (obj->refcount == 0) {
691#ifdef RTLD_DEBUG 691#ifdef RTLD_DEBUG
692 dbg(("unloading \"%s\"", obj->path)); 692 dbg(("unloading \"%s\"", obj->path));
693#endif 693#endif
694 if (obj->ehdr != MAP_FAILED) 694 if (obj->ehdr != MAP_FAILED)
695 munmap(obj->ehdr, _rtld_pagesz); 695 munmap(obj->ehdr, _rtld_pagesz);
696 munmap(obj->mapbase, obj->mapsize); 696 munmap(obj->mapbase, obj->mapsize);
697 _rtld_objlist_remove(&_rtld_list_global, obj); 697 _rtld_objlist_remove(&_rtld_list_global, obj);
698 _rtld_linkmap_delete(obj); 698 _rtld_linkmap_delete(obj);
699 *linkp = obj->next; 699 *linkp = obj->next;
700 _rtld_obj_free(obj); 700 _rtld_obj_free(obj);
701 } else 701 } else
702 linkp = &obj->next; 702 linkp = &obj->next;
703 } 703 }
704 _rtld_objtail = linkp; 704 _rtld_objtail = linkp;
705 } 705 }
706} 706}
707 707
708static void 708static void
709_rtld_unref_dag(Obj_Entry *root) 709_rtld_unref_dag(Obj_Entry *root)
710{ 710{
711 711
712 assert(root); 712 assert(root);
713 assert(root->refcount != 0); 713 assert(root->refcount != 0);
714 --root->refcount; 714 --root->refcount;
715 if (root->refcount == 0) { 715 if (root->refcount == 0) {
716 const Needed_Entry *needed; 716 const Needed_Entry *needed;
717 717
718 for (needed = root->needed; needed != NULL; 718 for (needed = root->needed; needed != NULL;
719 needed = needed->next) { 719 needed = needed->next) {
720 if (needed->obj != NULL) 720 if (needed->obj != NULL)
721 _rtld_unref_dag(needed->obj); 721 _rtld_unref_dag(needed->obj);
722 } 722 }
723 } 723 }
724} 724}
725 725
726__strong_alias(__dlclose,dlclose) 726__strong_alias(__dlclose,dlclose)
727int 727int
728dlclose(void *handle) 728dlclose(void *handle)
729{ 729{
730 Obj_Entry *root = _rtld_dlcheck(handle); 730 Obj_Entry *root = _rtld_dlcheck(handle);
731 731
732 if (root == NULL) 732 if (root == NULL)
733 return -1; 733 return -1;
734 734
735 _rtld_debug.r_state = RT_DELETE; 735 _rtld_debug.r_state = RT_DELETE;
736 _rtld_debug_state(); 736 _rtld_debug_state();
737 737
738 --root->dl_refcount; 738 --root->dl_refcount;
739 _rtld_unload_object(root, true); 739 _rtld_unload_object(root, true);
740 740
741 _rtld_debug.r_state = RT_CONSISTENT; 741 _rtld_debug.r_state = RT_CONSISTENT;
742 _rtld_debug_state(); 742 _rtld_debug_state();
743 743
744 return 0; 744 return 0;
745} 745}
746 746
747__strong_alias(__dlerror,dlerror) 747__strong_alias(__dlerror,dlerror)
748char * 748char *
749dlerror(void) 749dlerror(void)
750{ 750{
751 char *msg = error_message; 751 char *msg = error_message;
752 752
753 error_message = NULL; 753 error_message = NULL;
754 return msg; 754 return msg;
755} 755}
756 756
757__strong_alias(__dlopen,dlopen) 757__strong_alias(__dlopen,dlopen)
758void * 758void *
759dlopen(const char *name, int mode) 759dlopen(const char *name, int mode)
760{ 760{
761 Obj_Entry **old_obj_tail = _rtld_objtail; 761 Obj_Entry **old_obj_tail = _rtld_objtail;
762 Obj_Entry *obj = NULL; 762 Obj_Entry *obj = NULL;
763 763
764 _rtld_debug.r_state = RT_ADD; 764 _rtld_debug.r_state = RT_ADD;
765 _rtld_debug_state(); 765 _rtld_debug_state();
766 766
767 if (name == NULL) { 767 if (name == NULL) {
768 obj = _rtld_objmain; 768 obj = _rtld_objmain;
769 obj->refcount++; 769 obj->refcount++;
770 } else 770 } else
771 obj = _rtld_load_library(name, _rtld_objmain, mode); 771 obj = _rtld_load_library(name, _rtld_objmain, mode);
772 772
773 if (obj != NULL) { 773 if (obj != NULL) {
774 ++obj->dl_refcount; 774 ++obj->dl_refcount;
775 if (*old_obj_tail != NULL) { /* We loaded something new. */ 775 if (*old_obj_tail != NULL) { /* We loaded something new. */
776 assert(*old_obj_tail == obj); 776 assert(*old_obj_tail == obj);
777 777
778 if (_rtld_load_needed_objects(obj, mode) == -1 || 778 if (_rtld_load_needed_objects(obj, mode) == -1 ||
779 (_rtld_init_dag(obj), 779 (_rtld_init_dag(obj),
780 _rtld_relocate_objects(obj, 780 _rtld_relocate_objects(obj,
781 ((mode & 3) == RTLD_NOW))) == -1) { 781 ((mode & 3) == RTLD_NOW))) == -1) {
782 _rtld_unload_object(obj, false); 782 _rtld_unload_object(obj, false);
783 obj->dl_refcount--; 783 obj->dl_refcount--;
784 obj = NULL; 784 obj = NULL;
785 } else { 785 } else {
786 _rtld_call_init_functions(); 786 _rtld_call_init_functions();
787 } 787 }
788 } 788 }
789 } 789 }
790 _rtld_debug.r_state = RT_CONSISTENT; 790 _rtld_debug.r_state = RT_CONSISTENT;
791 _rtld_debug_state(); 791 _rtld_debug_state();
792 792
793 return obj; 793 return obj;
794} 794}
795 795
796/* 796/*
797 * Find a symbol in the main program. 797 * Find a symbol in the main program.
798 */ 798 */
799void * 799void *
800_rtld_objmain_sym(const char *name) 800_rtld_objmain_sym(const char *name)
801{ 801{
802 unsigned long hash; 802 unsigned long hash;
803 const Elf_Sym *def; 803 const Elf_Sym *def;
804 const Obj_Entry *obj; 804 const Obj_Entry *obj;
805 805
806 hash = _rtld_elf_hash(name); 806 hash = _rtld_elf_hash(name);
807 obj = _rtld_objmain; 807 obj = _rtld_objmain;
808 808
809 def = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, false); 809 def = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, false);
810 810
811 if (def != NULL) 811 if (def != NULL)
812 return obj->relocbase + def->st_value; 812 return obj->relocbase + def->st_value;
813 return(NULL); 813 return(NULL);
814} 814}
815 815
816#ifdef __powerpc__ 816#ifdef __powerpc__
817static void * 817static void *
818hackish_return_address(void) 818hackish_return_address(void)
819{ 819{
820 return __builtin_return_address(1); 820 return __builtin_return_address(1);
821} 821}
822#endif 822#endif
823 823
824__strong_alias(__dlsym,dlsym) 824__strong_alias(__dlsym,dlsym)
825void * 825void *
826dlsym(void *handle, const char *name) 826dlsym(void *handle, const char *name)
827{ 827{
828 const Obj_Entry *obj; 828 const Obj_Entry *obj;
829 unsigned long hash; 829 unsigned long hash;
830 const Elf_Sym *def; 830 const Elf_Sym *def;
831 const Obj_Entry *defobj; 831 const Obj_Entry *defobj;
832 void *retaddr; 832 void *retaddr;
833  833
834 hash = _rtld_elf_hash(name); 834 hash = _rtld_elf_hash(name);
835 def = NULL; 835 def = NULL;
836 defobj = NULL; 836 defobj = NULL;
837  837
838 switch ((intptr_t)handle) { 838 switch ((intptr_t)handle) {
839 case (intptr_t)NULL: 839 case (intptr_t)NULL:
840 case (intptr_t)RTLD_NEXT: 840 case (intptr_t)RTLD_NEXT:
841 case (intptr_t)RTLD_DEFAULT: 841 case (intptr_t)RTLD_DEFAULT:
842 case (intptr_t)RTLD_SELF: 842 case (intptr_t)RTLD_SELF:
843#ifdef __powerpc__ 843#ifdef __powerpc__
844 retaddr = hackish_return_address(); 844 retaddr = hackish_return_address();
845#else 845#else
846 retaddr = __builtin_return_address(0); 846 retaddr = __builtin_return_address(0);
847#endif 847#endif
848 if ((obj = _rtld_obj_from_addr(retaddr)) == NULL) { 848 if ((obj = _rtld_obj_from_addr(retaddr)) == NULL) {
849 _rtld_error("Cannot determine caller's shared object"); 849 _rtld_error("Cannot determine caller's shared object");
850 return NULL; 850 return NULL;
851 } 851 }
852 852
853 switch ((intptr_t)handle) { 853 switch ((intptr_t)handle) {
854 case (intptr_t)NULL: /* Just the caller's shared object. */ 854 case (intptr_t)NULL: /* Just the caller's shared object. */
855 def = _rtld_symlook_obj(name, hash, obj, false); 855 def = _rtld_symlook_obj(name, hash, obj, false);
856 defobj = obj; 856 defobj = obj;
857 break; 857 break;
858 858
859 case (intptr_t)RTLD_NEXT: /* Objects after callers */ 859 case (intptr_t)RTLD_NEXT: /* Objects after callers */
860 obj = obj->next; 860 obj = obj->next;
861 /*FALLTHROUGH*/ 861 /*FALLTHROUGH*/
862 862
863 case (intptr_t)RTLD_SELF: /* Caller included */ 863 case (intptr_t)RTLD_SELF: /* Caller included */
864 for (; obj; obj = obj->next) { 864 for (; obj; obj = obj->next) {
865 if ((def = _rtld_symlook_obj(name, hash, obj, 865 if ((def = _rtld_symlook_obj(name, hash, obj,
866 false)) != NULL) { 866 false)) != NULL) {
867 defobj = obj; 867 defobj = obj;
868 break; 868 break;
869 } 869 }
870 } 870 }
871 break; 871 break;
872 872
873 case (intptr_t)RTLD_DEFAULT: 873 case (intptr_t)RTLD_DEFAULT:
874 def = _rtld_symlook_default(name, hash, obj, &defobj, 874 def = _rtld_symlook_default(name, hash, obj, &defobj,
875 false); 875 false);
876 break; 876 break;
877 877
878 default: 878 default:
879 abort(); 879 abort();
880 } 880 }
881 break; 881 break;
882 882
883 default: 883 default:
884 if ((obj = _rtld_dlcheck(handle)) == NULL) 884 if ((obj = _rtld_dlcheck(handle)) == NULL)
885 return NULL; 885 return NULL;
886  886
887 if (obj->mainprog) { 887 if (obj->mainprog) {
888 /* Search main program and all libraries loaded by it */ 888 /* Search main program and all libraries loaded by it */
889 def = _rtld_symlook_list(name, hash, &_rtld_list_main, 889 def = _rtld_symlook_list(name, hash, &_rtld_list_main,
890 &defobj, false); 890 &defobj, false);
891 } else { 891 } else {
892 /* 892 Needed_Entry fake;
893 * XXX - This isn't correct. The search should include 893
894 * the whole DAG rooted at the given object. 894 /* Search the object and all the libraries loaded by it. */
895 */ 895 fake.next = NULL;
896 def = _rtld_symlook_obj(name, hash, obj, false); 896 fake.obj = (Obj_Entry *)obj;
897 defobj = obj; 897 fake.name = 0;
 898 def = _rtld_symlook_needed(name, hash, &fake, &defobj,
 899 false);
898 } 900 }
899 break; 901 break;
900 } 902 }
901  903
902 if (def != NULL) { 904 if (def != NULL) {
903#ifdef __HAVE_FUNCTION_DESCRIPTORS 905#ifdef __HAVE_FUNCTION_DESCRIPTORS
904 if (ELF_ST_TYPE(def->st_info) == STT_FUNC) 906 if (ELF_ST_TYPE(def->st_info) == STT_FUNC)
905 return (void *)_rtld_function_descriptor_alloc(defobj,  907 return (void *)_rtld_function_descriptor_alloc(defobj,
906 def, 0); 908 def, 0);
907#endif /* __HAVE_FUNCTION_DESCRIPTORS */ 909#endif /* __HAVE_FUNCTION_DESCRIPTORS */
908 return defobj->relocbase + def->st_value; 910 return defobj->relocbase + def->st_value;
909 } 911 }
910  912
911 _rtld_error("Undefined symbol \"%s\"", name); 913 _rtld_error("Undefined symbol \"%s\"", name);
912 return NULL; 914 return NULL;
913} 915}
914 916
915__strong_alias(__dladdr,dladdr) 917__strong_alias(__dladdr,dladdr)
916int 918int
917dladdr(const void *addr, Dl_info *info) 919dladdr(const void *addr, Dl_info *info)
918{ 920{
919 const Obj_Entry *obj; 921 const Obj_Entry *obj;
920 const Elf_Sym *def, *best_def; 922 const Elf_Sym *def, *best_def;
921 void *symbol_addr; 923 void *symbol_addr;
922 unsigned long symoffset; 924 unsigned long symoffset;
923  925
924#ifdef __HAVE_FUNCTION_DESCRIPTORS 926#ifdef __HAVE_FUNCTION_DESCRIPTORS
925 addr = _rtld_function_descriptor_function(addr); 927 addr = _rtld_function_descriptor_function(addr);
926#endif /* __HAVE_FUNCTION_DESCRIPTORS */ 928#endif /* __HAVE_FUNCTION_DESCRIPTORS */
927 929
928 obj = _rtld_obj_from_addr(addr); 930 obj = _rtld_obj_from_addr(addr);
929 if (obj == NULL) { 931 if (obj == NULL) {
930 _rtld_error("No shared object contains address"); 932 _rtld_error("No shared object contains address");
931 return 0; 933 return 0;
932 } 934 }
933 info->dli_fname = obj->path; 935 info->dli_fname = obj->path;
934 info->dli_fbase = obj->mapbase; 936 info->dli_fbase = obj->mapbase;
935 info->dli_saddr = (void *)0; 937 info->dli_saddr = (void *)0;
936 info->dli_sname = NULL; 938 info->dli_sname = NULL;
937  939
938 /* 940 /*
939 * Walk the symbol list looking for the symbol whose address is 941 * Walk the symbol list looking for the symbol whose address is
940 * closest to the address sent in. 942 * closest to the address sent in.
941 */ 943 */
942 best_def = NULL; 944 best_def = NULL;
943 for (symoffset = 0; symoffset < obj->nchains; symoffset++) { 945 for (symoffset = 0; symoffset < obj->nchains; symoffset++) {
944 def = obj->symtab + symoffset; 946 def = obj->symtab + symoffset;
945 947
946 /* 948 /*
947 * For skip the symbol if st_shndx is either SHN_UNDEF or 949 * For skip the symbol if st_shndx is either SHN_UNDEF or
948 * SHN_COMMON. 950 * SHN_COMMON.
949 */ 951 */
950 if (def->st_shndx == SHN_UNDEF || def->st_shndx == SHN_COMMON) 952 if (def->st_shndx == SHN_UNDEF || def->st_shndx == SHN_COMMON)
951 continue; 953 continue;
952 954
953 /* 955 /*
954 * If the symbol is greater than the specified address, or if it 956 * If the symbol is greater than the specified address, or if it
955 * is further away from addr than the current nearest symbol, 957 * is further away from addr than the current nearest symbol,
956 * then reject it. 958 * then reject it.
957 */ 959 */
958 symbol_addr = obj->relocbase + def->st_value; 960 symbol_addr = obj->relocbase + def->st_value;
959 if (symbol_addr > addr || symbol_addr < info->dli_saddr) 961 if (symbol_addr > addr || symbol_addr < info->dli_saddr)
960 continue; 962 continue;
961 963
962 /* Update our idea of the nearest symbol. */ 964 /* Update our idea of the nearest symbol. */
963 info->dli_sname = obj->strtab + def->st_name; 965 info->dli_sname = obj->strtab + def->st_name;
964 info->dli_saddr = symbol_addr; 966 info->dli_saddr = symbol_addr;
965 best_def = def; 967 best_def = def;
966 968
967 /* Exact match? */ 969 /* Exact match? */
968 if (info->dli_saddr == addr) 970 if (info->dli_saddr == addr)
969 break; 971 break;
970 } 972 }
971 973
972#ifdef __HAVE_FUNCTION_DESCRIPTORS 974#ifdef __HAVE_FUNCTION_DESCRIPTORS
973 if (best_def != NULL && ELF_ST_TYPE(best_def->st_info) == STT_FUNC) 975 if (best_def != NULL && ELF_ST_TYPE(best_def->st_info) == STT_FUNC)
974 info->dli_saddr = (void *)_rtld_function_descriptor_alloc(obj,  976 info->dli_saddr = (void *)_rtld_function_descriptor_alloc(obj,
975 best_def, 0); 977 best_def, 0);
976#endif /* __HAVE_FUNCTION_DESCRIPTORS */ 978#endif /* __HAVE_FUNCTION_DESCRIPTORS */
977 979
978 return 1; 980 return 1;
979} 981}
980 982
981/* 983/*
982 * Error reporting function. Use it like printf. If formats the message 984 * Error reporting function. Use it like printf. If formats the message
983 * into a buffer, and sets things up so that the next call to dlerror() 985 * into a buffer, and sets things up so that the next call to dlerror()
984 * will return the message. 986 * will return the message.
985 */ 987 */
986void 988void
987_rtld_error(const char *fmt,...) 989_rtld_error(const char *fmt,...)
988{ 990{
989 static char buf[512]; 991 static char buf[512];
990 va_list ap; 992 va_list ap;
991 993
992 va_start(ap, fmt); 994 va_start(ap, fmt);
993 xvsnprintf(buf, sizeof buf, fmt, ap); 995 xvsnprintf(buf, sizeof buf, fmt, ap);
994 error_message = buf; 996 error_message = buf;
995 va_end(ap); 997 va_end(ap);
996} 998}
997 999
998void 1000void
999_rtld_debug_state(void) 1001_rtld_debug_state(void)
1000{ 1002{
1001 1003
1002 /* do nothing */ 1004 /* do nothing */
1003} 1005}
1004 1006
1005void 1007void
1006_rtld_linkmap_add(Obj_Entry *obj) 1008_rtld_linkmap_add(Obj_Entry *obj)
1007{ 1009{
1008 struct link_map *l = &obj->linkmap; 1010 struct link_map *l = &obj->linkmap;
1009 struct link_map *prev; 1011 struct link_map *prev;
1010 1012
1011 obj->linkmap.l_name = obj->path; 1013 obj->linkmap.l_name = obj->path;
1012 obj->linkmap.l_addr = obj->relocbase; 1014 obj->linkmap.l_addr = obj->relocbase;
1013 obj->linkmap.l_ld = obj->dynamic; 1015 obj->linkmap.l_ld = obj->dynamic;
1014#ifdef __mips__ 1016#ifdef __mips__
1015 /* XXX This field is not standard and will be removed eventually. */ 1017 /* XXX This field is not standard and will be removed eventually. */
1016 obj->linkmap.l_offs = obj->relocbase; 1018 obj->linkmap.l_offs = obj->relocbase;
1017#endif 1019#endif
1018 1020
1019 if (_rtld_debug.r_map == NULL) { 1021 if (_rtld_debug.r_map == NULL) {
1020 _rtld_debug.r_map = l; 1022 _rtld_debug.r_map = l;
1021 return; 1023 return;
1022 } 1024 }
1023 1025
1024 /* 1026 /*
1025 * Scan to the end of the list, but not past the entry for the 1027 * Scan to the end of the list, but not past the entry for the
1026 * dynamic linker, which we want to keep at the very end. 1028 * dynamic linker, which we want to keep at the very end.
1027 */ 1029 */
1028 for (prev = _rtld_debug.r_map; 1030 for (prev = _rtld_debug.r_map;
1029 prev->l_next != NULL && prev->l_next != &_rtld_objself.linkmap; 1031 prev->l_next != NULL && prev->l_next != &_rtld_objself.linkmap;
1030 prev = prev->l_next); 1032 prev = prev->l_next);
1031 1033
1032 l->l_prev = prev; 1034 l->l_prev = prev;
1033 l->l_next = prev->l_next; 1035 l->l_next = prev->l_next;
1034 if (l->l_next != NULL) 1036 if (l->l_next != NULL)
1035 l->l_next->l_prev = l; 1037 l->l_next->l_prev = l;
1036 prev->l_next = l; 1038 prev->l_next = l;
1037} 1039}
1038 1040
1039void 1041void
1040_rtld_linkmap_delete(Obj_Entry *obj) 1042_rtld_linkmap_delete(Obj_Entry *obj)
1041{ 1043{
1042 struct link_map *l = &obj->linkmap; 1044 struct link_map *l = &obj->linkmap;
1043 1045
1044 if (l->l_prev == NULL) { 1046 if (l->l_prev == NULL) {
1045 if ((_rtld_debug.r_map = l->l_next) != NULL) 1047 if ((_rtld_debug.r_map = l->l_next) != NULL)
1046 l->l_next->l_prev = NULL; 1048 l->l_next->l_prev = NULL;
1047 return; 1049 return;
1048 } 1050 }
1049 if ((l->l_prev->l_next = l->l_next) != NULL) 1051 if ((l->l_prev->l_next = l->l_next) != NULL)
1050 l->l_next->l_prev = l->l_prev; 1052 l->l_next->l_prev = l->l_prev;
1051} 1053}
1052 1054
1053static Obj_Entry * 1055static Obj_Entry *
1054_rtld_obj_from_addr(const void *addr) 1056_rtld_obj_from_addr(const void *addr)
1055{ 1057{
1056 Obj_Entry *obj; 1058 Obj_Entry *obj;
1057  1059
1058 for (obj = _rtld_objlist; obj != NULL; obj = obj->next) { 1060 for (obj = _rtld_objlist; obj != NULL; obj = obj->next) {
1059 if (addr < (void *) obj->mapbase) 1061 if (addr < (void *) obj->mapbase)
1060 continue; 1062 continue;
1061 if (addr < (void *) (obj->mapbase + obj->mapsize)) 1063 if (addr < (void *) (obj->mapbase + obj->mapsize))
1062 return obj; 1064 return obj;
1063 } 1065 }
1064 return NULL; 1066 return NULL;
1065} 1067}
1066 1068
1067static void 1069static void
1068_rtld_objlist_clear(Objlist *list) 1070_rtld_objlist_clear(Objlist *list)
1069{ 1071{
1070 while (!SIMPLEQ_EMPTY(list)) { 1072 while (!SIMPLEQ_EMPTY(list)) {
1071 Objlist_Entry* elm = SIMPLEQ_FIRST(list); 1073 Objlist_Entry* elm = SIMPLEQ_FIRST(list);
1072 SIMPLEQ_REMOVE_HEAD(list, link); 1074 SIMPLEQ_REMOVE_HEAD(list, link);
1073 xfree(elm); 1075 xfree(elm);
1074 } 1076 }
1075} 1077}
1076 1078
1077static void 1079static void
1078_rtld_objlist_remove(Objlist *list, Obj_Entry *obj) 1080_rtld_objlist_remove(Objlist *list, Obj_Entry *obj)
1079{ 1081{
1080 Objlist_Entry *elm; 1082 Objlist_Entry *elm;
1081  1083
1082 if ((elm = _rtld_objlist_find(list, obj)) != NULL) { 1084 if ((elm = _rtld_objlist_find(list, obj)) != NULL) {
1083 SIMPLEQ_REMOVE(list, elm, Struct_Objlist_Entry, link); 1085 SIMPLEQ_REMOVE(list, elm, Struct_Objlist_Entry, link);
1084 xfree(elm); 1086 xfree(elm);
1085 } 1087 }
1086} 1088}

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

--- src/libexec/ld.elf_so/rtld.h 2008/06/03 19:32:32 1.78
+++ src/libexec/ld.elf_so/rtld.h 2008/10/04 09:37:12 1.79
@@ -1,292 +1,294 @@ @@ -1,292 +1,294 @@
1/* $NetBSD: rtld.h,v 1.78 2008/06/03 19:32:32 ad Exp $ */ 1/* $NetBSD: rtld.h,v 1.79 2008/10/04 09:37:12 skrll Exp $ */
2 2
3/* 3/*
4 * Copyright 1996 John D. Polstra. 4 * Copyright 1996 John D. Polstra.
5 * Copyright 1996 Matt Thomas <matt@3am-software.com> 5 * Copyright 1996 Matt Thomas <matt@3am-software.com>
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software 16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement: 17 * must display the following acknowledgement:
18 * This product includes software developed by John Polstra. 18 * This product includes software developed by John Polstra.
19 * 4. The name of the author may not be used to endorse or promote products 19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission. 20 * derived from this software without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */ 32 */
33 33
34#ifndef RTLD_H 34#ifndef RTLD_H
35#define RTLD_H 35#define RTLD_H
36 36
37#include <dlfcn.h> 37#include <dlfcn.h>
38#include <stdbool.h> 38#include <stdbool.h>
39#include <stddef.h> 39#include <stddef.h>
40#include <sys/param.h> 40#include <sys/param.h>
41#include <sys/types.h> 41#include <sys/types.h>
42#include <sys/queue.h> 42#include <sys/queue.h>
43#include <sys/exec_elf.h> 43#include <sys/exec_elf.h>
44#include "rtldenv.h" 44#include "rtldenv.h"
45#include "link.h" 45#include "link.h"
46 46
47#if defined(_RTLD_SOURCE) 47#if defined(_RTLD_SOURCE)
48 48
49#ifndef RTLD_DEFAULT_LIBRARY_PATH 49#ifndef RTLD_DEFAULT_LIBRARY_PATH
50#define RTLD_DEFAULT_LIBRARY_PATH "/usr/lib" 50#define RTLD_DEFAULT_LIBRARY_PATH "/usr/lib"
51#endif 51#endif
52#define _PATH_LD_HINTS "/etc/ld.so.conf" 52#define _PATH_LD_HINTS "/etc/ld.so.conf"
53 53
54extern int _rtld_pagesz; 54extern int _rtld_pagesz;
55 55
56#define round_down(x) ((x) & ~(_rtld_pagesz - 1)) 56#define round_down(x) ((x) & ~(_rtld_pagesz - 1))
57#define round_up(x) round_down((x) + _rtld_pagesz - 1) 57#define round_up(x) round_down((x) + _rtld_pagesz - 1)
58 58
59#define NEW(type) ((type *) xmalloc(sizeof(type))) 59#define NEW(type) ((type *) xmalloc(sizeof(type)))
60#define CNEW(type) ((type *) xcalloc(sizeof(type))) 60#define CNEW(type) ((type *) xcalloc(sizeof(type)))
61 61
62#endif /* _RTLD_SOURCE */ 62#endif /* _RTLD_SOURCE */
63 63
64/* 64/*
65 * C++ has mandated the use of the following keywords for its new boolean 65 * C++ has mandated the use of the following keywords for its new boolean
66 * type. We might as well follow their lead. 66 * type. We might as well follow their lead.
67 */ 67 */
68struct Struct_Obj_Entry; 68struct Struct_Obj_Entry;
69 69
70typedef struct Struct_Objlist_Entry { 70typedef struct Struct_Objlist_Entry {
71 SIMPLEQ_ENTRY(Struct_Objlist_Entry) link; 71 SIMPLEQ_ENTRY(Struct_Objlist_Entry) link;
72 struct Struct_Obj_Entry *obj; 72 struct Struct_Obj_Entry *obj;
73} Objlist_Entry; 73} Objlist_Entry;
74 74
75typedef SIMPLEQ_HEAD(Struct_Objlist, Struct_Objlist_Entry) Objlist; 75typedef SIMPLEQ_HEAD(Struct_Objlist, Struct_Objlist_Entry) Objlist;
76 76
77typedef struct Struct_Needed_Entry { 77typedef struct Struct_Needed_Entry {
78 struct Struct_Needed_Entry *next; 78 struct Struct_Needed_Entry *next;
79 struct Struct_Obj_Entry *obj; 79 struct Struct_Obj_Entry *obj;
80 unsigned long name; /* Offset of name in string table */ 80 unsigned long name; /* Offset of name in string table */
81} Needed_Entry; 81} Needed_Entry;
82 82
83typedef struct _rtld_search_path_t { 83typedef struct _rtld_search_path_t {
84 struct _rtld_search_path_t *sp_next; 84 struct _rtld_search_path_t *sp_next;
85 const char *sp_path; 85 const char *sp_path;
86 size_t sp_pathlen; 86 size_t sp_pathlen;
87} Search_Path; 87} Search_Path;
88 88
89 89
90#define RTLD_MAX_ENTRY 10 90#define RTLD_MAX_ENTRY 10
91#define RTLD_MAX_LIBRARY 4 91#define RTLD_MAX_LIBRARY 4
92#define RTLD_MAX_CTL 2 92#define RTLD_MAX_CTL 2
93typedef struct _rtld_library_xform_t { 93typedef struct _rtld_library_xform_t {
94 struct _rtld_library_xform_t *next; 94 struct _rtld_library_xform_t *next;
95 char *name; 95 char *name;
96 const char *ctlname; 96 const char *ctlname;
97 struct { 97 struct {
98 char *value; 98 char *value;
99 char *library[RTLD_MAX_LIBRARY]; 99 char *library[RTLD_MAX_LIBRARY];
100 } entry[RTLD_MAX_ENTRY]; 100 } entry[RTLD_MAX_ENTRY];
101} Library_Xform; 101} Library_Xform;
102 102
103/* 103/*
104 * Shared object descriptor. 104 * Shared object descriptor.
105 * 105 *
106 * Items marked with "(%)" are dynamically allocated, and must be freed 106 * Items marked with "(%)" are dynamically allocated, and must be freed
107 * when the structure is destroyed. 107 * when the structure is destroyed.
108 */ 108 */
109 109
110#define RTLD_MAGIC 0xd550b87a 110#define RTLD_MAGIC 0xd550b87a
111#define RTLD_VERSION 1 111#define RTLD_VERSION 1
112#define RTLD_MAIN 0x800 112#define RTLD_MAIN 0x800
113 113
114typedef struct Struct_Obj_Entry { 114typedef struct Struct_Obj_Entry {
115 Elf32_Word magic; /* Magic number (sanity check) */ 115 Elf32_Word magic; /* Magic number (sanity check) */
116 Elf32_Word version; /* Version number of struct format */ 116 Elf32_Word version; /* Version number of struct format */
117 117
118 struct Struct_Obj_Entry *next; 118 struct Struct_Obj_Entry *next;
119 char *path; /* Pathname of underlying file (%) */ 119 char *path; /* Pathname of underlying file (%) */
120 int refcount; 120 int refcount;
121 int dl_refcount; /* Number of times loaded by dlopen */ 121 int dl_refcount; /* Number of times loaded by dlopen */
122 122
123 /* These items are computed by map_object() or by digest_phdr(). */ 123 /* These items are computed by map_object() or by digest_phdr(). */
124 caddr_t mapbase; /* Base address of mapped region */ 124 caddr_t mapbase; /* Base address of mapped region */
125 size_t mapsize; /* Size of mapped region in bytes */ 125 size_t mapsize; /* Size of mapped region in bytes */
126 size_t textsize; /* Size of text segment in bytes */ 126 size_t textsize; /* Size of text segment in bytes */
127 Elf_Addr vaddrbase; /* Base address in shared object file */ 127 Elf_Addr vaddrbase; /* Base address in shared object file */
128 caddr_t relocbase; /* Reloc const = mapbase - *vaddrbase */ 128 caddr_t relocbase; /* Reloc const = mapbase - *vaddrbase */
129 Elf_Dyn *dynamic; /* Dynamic section */ 129 Elf_Dyn *dynamic; /* Dynamic section */
130 caddr_t entry; /* Entry point */ 130 caddr_t entry; /* Entry point */
131 const Elf_Phdr *__junk001; 131 const Elf_Phdr *__junk001;
132 size_t pathlen; /* Pathname length */ 132 size_t pathlen; /* Pathname length */
133 void *ehdr; 133 void *ehdr;
134 134
135 /* Items from the dynamic section. */ 135 /* Items from the dynamic section. */
136 Elf_Addr *pltgot; /* PLTGOT table */ 136 Elf_Addr *pltgot; /* PLTGOT table */
137 const Elf_Rel *rel; /* Relocation entries */ 137 const Elf_Rel *rel; /* Relocation entries */
138 const Elf_Rel *rellim; /* Limit of Relocation entries */ 138 const Elf_Rel *rellim; /* Limit of Relocation entries */
139 const Elf_Rela *rela; /* Relocation entries */ 139 const Elf_Rela *rela; /* Relocation entries */
140 const Elf_Rela *relalim; /* Limit of Relocation entries */ 140 const Elf_Rela *relalim; /* Limit of Relocation entries */
141 const Elf_Rel *pltrel; /* PLT relocation entries */ 141 const Elf_Rel *pltrel; /* PLT relocation entries */
142 const Elf_Rel *pltrellim; /* Limit of PLT relocation entries */ 142 const Elf_Rel *pltrellim; /* Limit of PLT relocation entries */
143 const Elf_Rela *pltrela; /* PLT relocation entries */ 143 const Elf_Rela *pltrela; /* PLT relocation entries */
144 const Elf_Rela *pltrelalim; /* Limit of PLT relocation entries */ 144 const Elf_Rela *pltrelalim; /* Limit of PLT relocation entries */
145 const Elf_Sym *symtab; /* Symbol table */ 145 const Elf_Sym *symtab; /* Symbol table */
146 const char *strtab; /* String table */ 146 const char *strtab; /* String table */
147 unsigned long strsize; /* Size in bytes of string table */ 147 unsigned long strsize; /* Size in bytes of string table */
148#ifdef __mips__ 148#ifdef __mips__
149 Elf_Word local_gotno; /* Number of local GOT entries */ 149 Elf_Word local_gotno; /* Number of local GOT entries */
150 Elf_Word symtabno; /* Number of dynamic symbols */ 150 Elf_Word symtabno; /* Number of dynamic symbols */
151 Elf_Word gotsym; /* First dynamic symbol in GOT */ 151 Elf_Word gotsym; /* First dynamic symbol in GOT */
152#endif 152#endif
153 153
154 const Elf_Word *buckets; /* Hash table buckets array */ 154 const Elf_Word *buckets; /* Hash table buckets array */
155 unsigned long nbuckets; /* Number of buckets */ 155 unsigned long nbuckets; /* Number of buckets */
156 const Elf_Word *chains; /* Hash table chain array */ 156 const Elf_Word *chains; /* Hash table chain array */
157 unsigned long nchains; /* Number of chains */ 157 unsigned long nchains; /* Number of chains */
158 158
159 Search_Path *rpaths; /* Search path specified in object */ 159 Search_Path *rpaths; /* Search path specified in object */
160 Needed_Entry *needed; /* Shared objects needed by this (%) */ 160 Needed_Entry *needed; /* Shared objects needed by this (%) */
161 161
162 void (*init)(void); /* Initialization function to call */ 162 void (*init)(void); /* Initialization function to call */
163 void (*fini)(void); /* Termination function to call */ 163 void (*fini)(void); /* Termination function to call */
164 164
165 /* Entry points for dlopen() and friends. */ 165 /* Entry points for dlopen() and friends. */
166 void *(*dlopen)(const char *, int); 166 void *(*dlopen)(const char *, int);
167 void *(*dlsym)(void *, const char *); 167 void *(*dlsym)(void *, const char *);
168 char *(*dlerror)(void); 168 char *(*dlerror)(void);
169 int (*dlclose)(void *); 169 int (*dlclose)(void *);
170 int (*dladdr)(const void *, Dl_info *); 170 int (*dladdr)(const void *, Dl_info *);
171 171
172 u_int32_t mainprog:1, /* True if this is the main program */ 172 u_int32_t mainprog:1, /* True if this is the main program */
173 rtld:1, /* True if this is the dynamic linker */ 173 rtld:1, /* True if this is the dynamic linker */
174 textrel:1, /* True if there are relocations to 174 textrel:1, /* True if there are relocations to
175 * text seg */ 175 * text seg */
176 symbolic:1, /* True if generated with 176 symbolic:1, /* True if generated with
177 * "-Bsymbolic" */ 177 * "-Bsymbolic" */
178 printed:1, /* True if ldd has printed it */ 178 printed:1, /* True if ldd has printed it */
179 isdynamic:1, /* True if this is a pure PIC object */ 179 isdynamic:1, /* True if this is a pure PIC object */
180 mainref:1, /* True if on _rtld_list_main */ 180 mainref:1, /* True if on _rtld_list_main */
181 globalref:1, /* True if on _rtld_list_global */ 181 globalref:1, /* True if on _rtld_list_global */
182 init_done:1, /* True if .init has been added */ 182 init_done:1, /* True if .init has been added */
183 init_called:1, /* True if .init function has been  183 init_called:1, /* True if .init function has been
184 * called */ 184 * called */
185 fini_called:1, /* True if .fini function has been  185 fini_called:1, /* True if .fini function has been
186 * called */ 186 * called */
187 initfirst:1; /* True if object's .init/.fini take 187 initfirst:1; /* True if object's .init/.fini take
188 * priority over others */ 188 * priority over others */
189 189
190 struct link_map linkmap; /* for GDB */ 190 struct link_map linkmap; /* for GDB */
191 191
192 /* These items are computed by map_object() or by digest_phdr(). */ 192 /* These items are computed by map_object() or by digest_phdr(). */
193 const char *interp; /* Pathname of the interpreter, if any */ 193 const char *interp; /* Pathname of the interpreter, if any */
194 Objlist dldags; /* Object belongs to these dlopened DAGs (%) */ 194 Objlist dldags; /* Object belongs to these dlopened DAGs (%) */
195 Objlist dagmembers; /* DAG has these members (%) */ 195 Objlist dagmembers; /* DAG has these members (%) */
196 dev_t dev; /* Object's filesystem's device */ 196 dev_t dev; /* Object's filesystem's device */
197 ino_t ino; /* Object's inode number */ 197 ino_t ino; /* Object's inode number */
198} Obj_Entry; 198} Obj_Entry;
199 199
200#if defined(_RTLD_SOURCE) 200#if defined(_RTLD_SOURCE)
201 201
202extern struct r_debug _rtld_debug; 202extern struct r_debug _rtld_debug;
203extern Search_Path *_rtld_default_paths; 203extern Search_Path *_rtld_default_paths;
204extern Obj_Entry *_rtld_objlist; 204extern Obj_Entry *_rtld_objlist;
205extern Obj_Entry **_rtld_objtail; 205extern Obj_Entry **_rtld_objtail;
206extern Obj_Entry *_rtld_objmain; 206extern Obj_Entry *_rtld_objmain;
207extern Obj_Entry _rtld_objself; 207extern Obj_Entry _rtld_objself;
208extern Search_Path *_rtld_paths; 208extern Search_Path *_rtld_paths;
209extern Library_Xform *_rtld_xforms; 209extern Library_Xform *_rtld_xforms;
210extern bool _rtld_trust; 210extern bool _rtld_trust;
211extern Objlist _rtld_list_global; 211extern Objlist _rtld_list_global;
212extern Objlist _rtld_list_main; 212extern Objlist _rtld_list_main;
213extern Elf_Sym _rtld_sym_zero; 213extern Elf_Sym _rtld_sym_zero;
214 214
215/* rtld.c */ 215/* rtld.c */
216 216
217/* 217/*
218 * We export these symbols using _rtld_symbol_lookup and is_exported. 218 * We export these symbols using _rtld_symbol_lookup and is_exported.
219 */ 219 */
220char *dlerror(void); 220char *dlerror(void);
221void *dlopen(const char *, int); 221void *dlopen(const char *, int);
222void *dlsym(void *, const char *); 222void *dlsym(void *, const char *);
223int dlclose(void *); 223int dlclose(void *);
224int dladdr(const void *, Dl_info *); 224int dladdr(const void *, Dl_info *);
225 225
226void _rtld_error(const char *, ...) 226void _rtld_error(const char *, ...)
227 __attribute__((__format__(__printf__,1,2))); 227 __attribute__((__format__(__printf__,1,2)));
228void _rtld_die(void) __attribute__((__noreturn__)); 228void _rtld_die(void) __attribute__((__noreturn__));
229void *_rtld_objmain_sym(const char *); 229void *_rtld_objmain_sym(const char *);
230void _rtld_debug_state(void); 230void _rtld_debug_state(void);
231void _rtld_linkmap_add(Obj_Entry *); 231void _rtld_linkmap_add(Obj_Entry *);
232void _rtld_linkmap_delete(Obj_Entry *); 232void _rtld_linkmap_delete(Obj_Entry *);
233void _rtld_objlist_push_head(Objlist *, Obj_Entry *); 233void _rtld_objlist_push_head(Objlist *, Obj_Entry *);
234void _rtld_objlist_push_tail(Objlist *, Obj_Entry *); 234void _rtld_objlist_push_tail(Objlist *, Obj_Entry *);
235Objlist_Entry *_rtld_objlist_find(Objlist *, const Obj_Entry *); 235Objlist_Entry *_rtld_objlist_find(Objlist *, const Obj_Entry *);
236 236
237/* expand.c */ 237/* expand.c */
238size_t _rtld_expand_path(char *, size_t, const char *, const char *,\ 238size_t _rtld_expand_path(char *, size_t, const char *, const char *,\
239 const char *); 239 const char *);
240 240
241/* headers.c */ 241/* headers.c */
242void _rtld_digest_dynamic(const char *, Obj_Entry *); 242void _rtld_digest_dynamic(const char *, Obj_Entry *);
243Obj_Entry *_rtld_digest_phdr(const Elf_Phdr *, int, caddr_t); 243Obj_Entry *_rtld_digest_phdr(const Elf_Phdr *, int, caddr_t);
244 244
245/* load.c */ 245/* load.c */
246Obj_Entry *_rtld_load_object(const char *, int); 246Obj_Entry *_rtld_load_object(const char *, int);
247int _rtld_load_needed_objects(Obj_Entry *, int); 247int _rtld_load_needed_objects(Obj_Entry *, int);
248int _rtld_preload(const char *); 248int _rtld_preload(const char *);
249 249
250/* path.c */ 250/* path.c */
251void _rtld_add_paths(const char *, Search_Path **, const char *); 251void _rtld_add_paths(const char *, Search_Path **, const char *);
252void _rtld_process_hints(const char *, Search_Path **, Library_Xform **, 252void _rtld_process_hints(const char *, Search_Path **, Library_Xform **,
253 const char *); 253 const char *);
254int _rtld_sysctl(const char *, void *, size_t *); 254int _rtld_sysctl(const char *, void *, size_t *);
255 255
256/* reloc.c */ 256/* reloc.c */
257int _rtld_do_copy_relocations(const Obj_Entry *); 257int _rtld_do_copy_relocations(const Obj_Entry *);
258int _rtld_relocate_objects(Obj_Entry *, bool); 258int _rtld_relocate_objects(Obj_Entry *, bool);
259int _rtld_relocate_nonplt_objects(const Obj_Entry *); 259int _rtld_relocate_nonplt_objects(const Obj_Entry *);
260int _rtld_relocate_plt_lazy(const Obj_Entry *); 260int _rtld_relocate_plt_lazy(const Obj_Entry *);
261int _rtld_relocate_plt_objects(const Obj_Entry *); 261int _rtld_relocate_plt_objects(const Obj_Entry *);
262void _rtld_setup_pltgot(const Obj_Entry *); 262void _rtld_setup_pltgot(const Obj_Entry *);
263 263
264/* search.c */ 264/* search.c */
265Obj_Entry *_rtld_load_library(const char *, const Obj_Entry *, int); 265Obj_Entry *_rtld_load_library(const char *, const Obj_Entry *, int);
266 266
267/* symbol.c */ 267/* symbol.c */
268unsigned long _rtld_elf_hash(const char *); 268unsigned long _rtld_elf_hash(const char *);
269const Elf_Sym *_rtld_symlook_obj(const char *, unsigned long, 269const Elf_Sym *_rtld_symlook_obj(const char *, unsigned long,
270 const Obj_Entry *, bool); 270 const Obj_Entry *, bool);
271const Elf_Sym *_rtld_find_symdef(unsigned long, const Obj_Entry *, 271const Elf_Sym *_rtld_find_symdef(unsigned long, const Obj_Entry *,
272 const Obj_Entry **, bool); 272 const Obj_Entry **, bool);
273const Elf_Sym *_rtld_symlook_list(const char *, unsigned long, 273const Elf_Sym *_rtld_symlook_list(const char *, unsigned long,
274 const Objlist *, const Obj_Entry **, bool); 274 const Objlist *, const Obj_Entry **, bool);
275const Elf_Sym *_rtld_symlook_default(const char *, unsigned long, 275const Elf_Sym *_rtld_symlook_default(const char *, unsigned long,
276 const Obj_Entry *, const Obj_Entry **, bool); 276 const Obj_Entry *, const Obj_Entry **, bool);
 277const Elf_Sym *_rtld_symlook_needed(const char *, unsigned long,
 278 const Needed_Entry *, const Obj_Entry **, bool);
277 279
278/* map_object.c */ 280/* map_object.c */
279Obj_Entry *_rtld_map_object(const char *, int, const struct stat *); 281Obj_Entry *_rtld_map_object(const char *, int, const struct stat *);
280void _rtld_obj_free(Obj_Entry *); 282void _rtld_obj_free(Obj_Entry *);
281Obj_Entry *_rtld_obj_new(void); 283Obj_Entry *_rtld_obj_new(void);
282 284
283/* function descriptors */ 285/* function descriptors */
284#ifdef __HAVE_FUNCTION_DESCRIPTORS 286#ifdef __HAVE_FUNCTION_DESCRIPTORS
285Elf_Addr _rtld_function_descriptor_alloc(const Obj_Entry *,  287Elf_Addr _rtld_function_descriptor_alloc(const Obj_Entry *,
286 const Elf_Sym *, Elf_Addr); 288 const Elf_Sym *, Elf_Addr);
287const void *_rtld_function_descriptor_function(const void *); 289const void *_rtld_function_descriptor_function(const void *);
288#endif /* __HAVE_FUNCTION_DESCRIPTORS */ 290#endif /* __HAVE_FUNCTION_DESCRIPTORS */
289 291
290#endif /* _RTLD_SOURCE */ 292#endif /* _RTLD_SOURCE */
291 293
292#endif /* RTLD_H */ 294#endif /* RTLD_H */

cvs diff -r1.46 -r1.47 src/libexec/ld.elf_so/symbol.c (switch to unified diff)

--- src/libexec/ld.elf_so/symbol.c 2008/07/24 04:39:25 1.46
+++ src/libexec/ld.elf_so/symbol.c 2008/10/04 09:37:12 1.47
@@ -1,370 +1,420 @@ @@ -1,370 +1,420 @@
1/* $NetBSD: symbol.c,v 1.46 2008/07/24 04:39:25 matt Exp $ */ 1/* $NetBSD: symbol.c,v 1.47 2008/10/04 09:37:12 skrll 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: symbol.c,v 1.46 2008/07/24 04:39:25 matt Exp $"); 43__RCSID("$NetBSD: symbol.c,v 1.47 2008/10/04 09:37:12 skrll Exp $");
44#endif /* not lint */ 44#endif /* not lint */
45 45
46#include <err.h> 46#include <err.h>
47#include <errno.h> 47#include <errno.h>
48#include <fcntl.h> 48#include <fcntl.h>
49#include <stdarg.h> 49#include <stdarg.h>
50#include <stdio.h> 50#include <stdio.h>
51#include <stdlib.h> 51#include <stdlib.h>
52#include <string.h> 52#include <string.h>
53#include <unistd.h> 53#include <unistd.h>
54#include <sys/types.h> 54#include <sys/types.h>
55#include <sys/mman.h> 55#include <sys/mman.h>
56#include <dirent.h> 56#include <dirent.h>
57 57
58#include "debug.h" 58#include "debug.h"
59#include "rtld.h" 59#include "rtld.h"
60 60
61typedef void (*fptr_t)(void); 61typedef void (*fptr_t)(void);
62 62
63static bool 63static bool
64_rtld_is_exported(const Elf_Sym *def) 64_rtld_is_exported(const Elf_Sym *def)
65{ 65{
66 static const fptr_t _rtld_exports[] = { 66 static const fptr_t _rtld_exports[] = {
67 (fptr_t)dlopen, 67 (fptr_t)dlopen,
68 (fptr_t)dlclose, 68 (fptr_t)dlclose,
69 (fptr_t)dlsym, 69 (fptr_t)dlsym,
70 (fptr_t)dlerror, 70 (fptr_t)dlerror,
71 (fptr_t)dladdr, 71 (fptr_t)dladdr,
72 NULL 72 NULL
73 }; 73 };
74 int i; 74 int i;
75 fptr_t value; 75 fptr_t value;
76 76
77 value = (fptr_t)(_rtld_objself.relocbase + def->st_value); 77 value = (fptr_t)(_rtld_objself.relocbase + def->st_value);
78 for (i = 0; _rtld_exports[i] != NULL; i++) { 78 for (i = 0; _rtld_exports[i] != NULL; i++) {
79 if (value == _rtld_exports[i]) 79 if (value == _rtld_exports[i])
80 return true; 80 return true;
81 } 81 }
82 return false; 82 return false;
83} 83}
84 84
85/* 85/*
86 * Hash function for symbol table lookup. Don't even think about changing 86 * Hash function for symbol table lookup. Don't even think about changing
87 * this. It is specified by the System V ABI. 87 * this. It is specified by the System V ABI.
88 */ 88 */
89unsigned long 89unsigned long
90_rtld_elf_hash(const char *name) 90_rtld_elf_hash(const char *name)
91{ 91{
92 const unsigned char *p = (const unsigned char *) name; 92 const unsigned char *p = (const unsigned char *) name;
93 unsigned long h = 0; 93 unsigned long h = 0;
94 unsigned long g; 94 unsigned long g;
95 unsigned long c; 95 unsigned long c;
96 96
97 for (; __predict_true((c = *p) != '\0'); p++) { 97 for (; __predict_true((c = *p) != '\0'); p++) {
98 h <<= 4; 98 h <<= 4;
99 h += c; 99 h += c;
100 if ((g = h & 0xf0000000) != 0) { 100 if ((g = h & 0xf0000000) != 0) {
101 h ^= g; 101 h ^= g;
102 h ^= g >> 24; 102 h ^= g >> 24;
103 } 103 }
104 } 104 }
105 return (h); 105 return (h);
106} 106}
107 107
108const Elf_Sym * 108const Elf_Sym *
109_rtld_symlook_list(const char *name, unsigned long hash, const Objlist *objlist, 109_rtld_symlook_list(const char *name, unsigned long hash, const Objlist *objlist,
110 const Obj_Entry **defobj_out, bool in_plt) 110 const Obj_Entry **defobj_out, bool in_plt)
111{ 111{
112 const Elf_Sym *symp; 112 const Elf_Sym *symp;
113 const Elf_Sym *def; 113 const Elf_Sym *def;
114 const Obj_Entry *defobj; 114 const Obj_Entry *defobj;
115 const Objlist_Entry *elm; 115 const Objlist_Entry *elm;
116  116
117 def = NULL; 117 def = NULL;
118 defobj = NULL; 118 defobj = NULL;
119 SIMPLEQ_FOREACH(elm, objlist, link) { 119 SIMPLEQ_FOREACH(elm, objlist, link) {
120 rdbg(("search object %p (%s) for %s", elm->obj, elm->obj->path, 120 rdbg(("search object %p (%s) for %s", elm->obj, elm->obj->path,
121 name)); 121 name));
122 if ((symp = _rtld_symlook_obj(name, hash, elm->obj, in_plt)) 122 if ((symp = _rtld_symlook_obj(name, hash, elm->obj, in_plt))
123 != NULL) { 123 != NULL) {
124 if ((def == NULL) || 124 if ((def == NULL) ||
125 (ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 125 (ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
126 def = symp; 126 def = symp;
127 defobj = elm->obj; 127 defobj = elm->obj;
128 if (ELF_ST_BIND(def->st_info) != STB_WEAK) 128 if (ELF_ST_BIND(def->st_info) != STB_WEAK)
129 break; 129 break;
130 } 130 }
131 } 131 }
132 } 132 }
133 if (def != NULL) 133 if (def != NULL)
134 *defobj_out = defobj; 134 *defobj_out = defobj;
135 return def; 135 return def;
136} 136}
137 137
138/* 138/*
 139 * Search the symbol table of a shared object and all objects needed by it for
 140 * a symbol of the given name. Search order is breadth-first. Returns a pointer
 141 * to the symbol, or NULL if no definition was found.
 142 */
 143const Elf_Sym *
 144_rtld_symlook_needed(const char *name, unsigned long hash,
 145 const Needed_Entry *needed, const Obj_Entry **defobj_out, bool inplt)
 146{
 147 const Elf_Sym *def, *def_w;
 148 const Needed_Entry *n;
 149 const Obj_Entry *obj, *defobj, *defobj1;
 150
 151 def = def_w = NULL;
 152 defobj = NULL;
 153 for (n = needed; n != NULL; n = n->next) {
 154 if ((obj = n->obj) == NULL ||
 155 (def = _rtld_symlook_obj(name, hash, obj, inplt)) == NULL)
 156 continue;
 157 defobj = obj;
 158 if (ELF_ST_BIND(def->st_info) != STB_WEAK) {
 159 *defobj_out = defobj;
 160
 161 return (def);
 162 }
 163 }
 164 /*
 165 * Either the symbol definition has not been found in directly needed
 166 * objects, or the found symbol is weak.
 167 */
 168 for (n = needed; n != NULL; n = n->next) {
 169 if ((obj = n->obj) == NULL)
 170 continue;
 171 def_w = _rtld_symlook_needed(name, hash, obj->needed, &defobj1,
 172 inplt);
 173 if (def_w == NULL)
 174 continue;
 175 if (def == NULL || ELF_ST_BIND(def_w->st_info) != STB_WEAK) {
 176 def = def_w;
 177 defobj = defobj1;
 178 if (ELF_ST_BIND(def_w->st_info) != STB_WEAK)
 179 break;
 180 }
 181 }
 182 if (def != NULL)
 183 *defobj_out = defobj;
 184
 185 return def;
 186}
 187
 188/*
139 * Search the symbol table of a single shared object for a symbol of 189 * Search the symbol table of a single shared object for a symbol of
140 * the given name. Returns a pointer to the symbol, or NULL if no 190 * the given name. Returns a pointer to the symbol, or NULL if no
141 * definition was found. 191 * definition was found.
142 * 192 *
143 * The symbol's hash value is passed in for efficiency reasons; that 193 * The symbol's hash value is passed in for efficiency reasons; that
144 * eliminates many recomputations of the hash value. 194 * eliminates many recomputations of the hash value.
145 */ 195 */
146const Elf_Sym * 196const Elf_Sym *
147_rtld_symlook_obj(const char *name, unsigned long hash, 197_rtld_symlook_obj(const char *name, unsigned long hash,
148 const Obj_Entry *obj, bool in_plt) 198 const Obj_Entry *obj, bool in_plt)
149{ 199{
150 unsigned long symnum; 200 unsigned long symnum;
151 201
152 for (symnum = obj->buckets[hash % obj->nbuckets]; 202 for (symnum = obj->buckets[hash % obj->nbuckets];
153 symnum != ELF_SYM_UNDEFINED; 203 symnum != ELF_SYM_UNDEFINED;
154 symnum = obj->chains[symnum]) { 204 symnum = obj->chains[symnum]) {
155 const Elf_Sym *symp; 205 const Elf_Sym *symp;
156 const char *strp; 206 const char *strp;
157 207
158 assert(symnum < obj->nchains); 208 assert(symnum < obj->nchains);
159 symp = obj->symtab + symnum; 209 symp = obj->symtab + symnum;
160 strp = obj->strtab + symp->st_name; 210 strp = obj->strtab + symp->st_name;
161 rdbg(("check \"%s\" vs \"%s\" in %p", name, strp, obj)); 211 rdbg(("check \"%s\" vs \"%s\" in %p", name, strp, obj));
162 if (name[1] == strp[1] && !strcmp(name, strp)) { 212 if (name[1] == strp[1] && !strcmp(name, strp)) {
163 if (symp->st_shndx != SHN_UNDEF) 213 if (symp->st_shndx != SHN_UNDEF)
164 return symp; 214 return symp;
165#ifndef __mips__ 215#ifndef __mips__
166 /* 216 /*
167 * XXX DANGER WILL ROBINSON! 217 * XXX DANGER WILL ROBINSON!
168 * If we have a function pointer in the executable's 218 * If we have a function pointer in the executable's
169 * data section, it points to the executable's PLT 219 * data section, it points to the executable's PLT
170 * slot, and there is NO relocation emitted. To make 220 * slot, and there is NO relocation emitted. To make
171 * the function pointer comparable to function pointers 221 * the function pointer comparable to function pointers
172 * in shared libraries, we must resolve data references 222 * in shared libraries, we must resolve data references
173 * in the libraries to point to PLT slots in the 223 * in the libraries to point to PLT slots in the
174 * executable, if they exist. 224 * executable, if they exist.
175 */ 225 */
176 else if (!in_plt && symp->st_value != 0 && 226 else if (!in_plt && symp->st_value != 0 &&
177 ELF_ST_TYPE(symp->st_info) == STT_FUNC) 227 ELF_ST_TYPE(symp->st_info) == STT_FUNC)
178 return symp; 228 return symp;
179#endif 229#endif
180 else 230 else
181 return NULL; 231 return NULL;
182 } 232 }
183 } 233 }
184 234
185 return NULL; 235 return NULL;
186} 236}
187 237
188/* 238/*
189 * Given a symbol number in a referencing object, find the corresponding 239 * Given a symbol number in a referencing object, find the corresponding
190 * definition of the symbol. Returns a pointer to the symbol, or NULL if 240 * definition of the symbol. Returns a pointer to the symbol, or NULL if
191 * no definition was found. Returns a pointer to the Obj_Entry of the 241 * no definition was found. Returns a pointer to the Obj_Entry of the
192 * defining object via the reference parameter DEFOBJ_OUT. 242 * defining object via the reference parameter DEFOBJ_OUT.
193 */ 243 */
194const Elf_Sym * 244const Elf_Sym *
195_rtld_find_symdef(unsigned long symnum, const Obj_Entry *refobj, 245_rtld_find_symdef(unsigned long symnum, const Obj_Entry *refobj,
196 const Obj_Entry **defobj_out, bool in_plt) 246 const Obj_Entry **defobj_out, bool in_plt)
197{ 247{
198 const Elf_Sym *ref; 248 const Elf_Sym *ref;
199 const Elf_Sym *def; 249 const Elf_Sym *def;
200 const Obj_Entry *defobj; 250 const Obj_Entry *defobj;
201 const char *name; 251 const char *name;
202 unsigned long hash; 252 unsigned long hash;
203 253
204#ifdef COMBRELOC 254#ifdef COMBRELOC
205 /* 255 /*
206 * COMBRELOC combines multiple reloc sections and sorts them to make 256 * COMBRELOC combines multiple reloc sections and sorts them to make
207 * dynamic symbol lookup caching possible. 257 * dynamic symbol lookup caching possible.
208 * 258 *
209 * So if the lookup we are doing is the same as the previous lookup 259 * So if the lookup we are doing is the same as the previous lookup
210 * return the cached results. 260 * return the cached results.
211 */ 261 */
212 static unsigned long last_symnum; 262 static unsigned long last_symnum;
213 static const Elf_Sym *last_def; 263 static const Elf_Sym *last_def;
214 static const Obj_Entry *last_refobj; 264 static const Obj_Entry *last_refobj;
215 static const Obj_Entry *last_defobj; 265 static const Obj_Entry *last_defobj;
216 266
217 if (symnum == last_symnum && refobj == last_refobj 267 if (symnum == last_symnum && refobj == last_refobj
218 && in_plt == false) { 268 && in_plt == false) {
219 *defobj_out = last_defobj; 269 *defobj_out = last_defobj;
220 return last_def; 270 return last_def;
221 } 271 }
222#endif 272#endif
223 273
224 ref = refobj->symtab + symnum; 274 ref = refobj->symtab + symnum;
225 name = refobj->strtab + ref->st_name; 275 name = refobj->strtab + ref->st_name;
226 276
227 /* 277 /*
228 * We don't have to do a full scale lookup if the symbol is local. 278 * We don't have to do a full scale lookup if the symbol is local.
229 * We know it will bind to the instance in this load module; to 279 * We know it will bind to the instance in this load module; to
230 * which we already have a pointer (ie ref). 280 * which we already have a pointer (ie ref).
231 */ 281 */
232 if (ELF_ST_BIND(ref->st_info) != STB_LOCAL) { 282 if (ELF_ST_BIND(ref->st_info) != STB_LOCAL) {
233 if (ELF_ST_TYPE(ref->st_info) == STT_SECTION) { 283 if (ELF_ST_TYPE(ref->st_info) == STT_SECTION) {
234 _rtld_error("%s: Bogus symbol table entry %lu", 284 _rtld_error("%s: Bogus symbol table entry %lu",
235 refobj->path, symnum); 285 refobj->path, symnum);
236 } 286 }
237 287
238 hash = _rtld_elf_hash(name); 288 hash = _rtld_elf_hash(name);
239 defobj = NULL; 289 defobj = NULL;
240 def = _rtld_symlook_default(name, hash, refobj, &defobj, in_plt); 290 def = _rtld_symlook_default(name, hash, refobj, &defobj, in_plt);
241 } else { 291 } else {
242 rdbg(("STB_LOCAL symbol %s in %s", name, refobj->path)); 292 rdbg(("STB_LOCAL symbol %s in %s", name, refobj->path));
243 def = ref; 293 def = ref;
244 defobj = refobj; 294 defobj = refobj;
245 } 295 }
246  296
247 /* 297 /*
248 * If we found no definition and the reference is weak, treat the 298 * If we found no definition and the reference is weak, treat the
249 * symbol as having the value zero. 299 * symbol as having the value zero.
250 */ 300 */
251 if (def == NULL && ELF_ST_BIND(ref->st_info) == STB_WEAK) { 301 if (def == NULL && ELF_ST_BIND(ref->st_info) == STB_WEAK) {
252 if (in_plt) { 302 if (in_plt) {
253 _rtld_error( 303 _rtld_error(
254 "%s: Trying to call undefined weak symbol `%s'", 304 "%s: Trying to call undefined weak symbol `%s'",
255 refobj->path, name); 305 refobj->path, name);
256 } 306 }
257 rdbg((" returning _rtld_sym_zero@_rtld_objself")); 307 rdbg((" returning _rtld_sym_zero@_rtld_objself"));
258 def = &_rtld_sym_zero; 308 def = &_rtld_sym_zero;
259 defobj = &_rtld_objself; 309 defobj = &_rtld_objself;
260 } 310 }
261 311
262 if (def != NULL) { 312 if (def != NULL) {
263 *defobj_out = defobj; 313 *defobj_out = defobj;
264#ifdef COMBRELOC 314#ifdef COMBRELOC
265 if (in_plt == false) { 315 if (in_plt == false) {
266 /* 316 /*
267 * Cache the lookup arguments and results if this was 317 * Cache the lookup arguments and results if this was
268 * non-PLT lookup. 318 * non-PLT lookup.
269 */ 319 */
270 last_symnum = symnum; 320 last_symnum = symnum;
271 last_refobj = refobj; 321 last_refobj = refobj;
272 last_def = def; 322 last_def = def;
273 last_defobj = defobj; 323 last_defobj = defobj;
274 } 324 }
275#endif 325#endif
276 } else { 326 } else {
277 rdbg(("lookup failed")); 327 rdbg(("lookup failed"));
278 _rtld_error("%s: Undefined %ssymbol \"%s\" (symnum = %ld)", 328 _rtld_error("%s: Undefined %ssymbol \"%s\" (symnum = %ld)",
279 refobj->path, in_plt ? "PLT " : "", name, symnum); 329 refobj->path, in_plt ? "PLT " : "", name, symnum);
280 } 330 }
281 return def; 331 return def;
282} 332}
283 333
284/* 334/*
285 * Given a symbol name in a referencing object, find the corresponding 335 * Given a symbol name in a referencing object, find the corresponding
286 * definition of the symbol. Returns a pointer to the symbol, or NULL if 336 * definition of the symbol. Returns a pointer to the symbol, or NULL if
287 * no definition was found. Returns a pointer to the Obj_Entry of the 337 * no definition was found. Returns a pointer to the Obj_Entry of the
288 * defining object via the reference parameter DEFOBJ_OUT. 338 * defining object via the reference parameter DEFOBJ_OUT.
289 */ 339 */
290const Elf_Sym * 340const Elf_Sym *
291_rtld_symlook_default(const char *name, unsigned long hash, 341_rtld_symlook_default(const char *name, unsigned long hash,
292 const Obj_Entry *refobj, const Obj_Entry **defobj_out, bool in_plt) 342 const Obj_Entry *refobj, const Obj_Entry **defobj_out, bool in_plt)
293{ 343{
294 const Elf_Sym *def; 344 const Elf_Sym *def;
295 const Elf_Sym *symp; 345 const Elf_Sym *symp;
296 const Obj_Entry *obj; 346 const Obj_Entry *obj;
297 const Obj_Entry *defobj; 347 const Obj_Entry *defobj;
298 const Objlist_Entry *elm; 348 const Objlist_Entry *elm;
299 def = NULL; 349 def = NULL;
300 defobj = NULL; 350 defobj = NULL;
301 351
302 /* Look first in the referencing object if linked symbolically. */ 352 /* Look first in the referencing object if linked symbolically. */
303 if (refobj->symbolic) { 353 if (refobj->symbolic) {
304 rdbg(("search referencing object for %s", name)); 354 rdbg(("search referencing object for %s", name));
305 symp = _rtld_symlook_obj(name, hash, refobj, in_plt); 355 symp = _rtld_symlook_obj(name, hash, refobj, in_plt);
306 if (symp != NULL) { 356 if (symp != NULL) {
307 def = symp; 357 def = symp;
308 defobj = refobj; 358 defobj = refobj;
309 } 359 }
310 } 360 }
311 361
312 /* Search all objects loaded at program start up. */ 362 /* Search all objects loaded at program start up. */
313 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { 363 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) {
314 rdbg(("search _rtld_list_main for %s", name)); 364 rdbg(("search _rtld_list_main for %s", name));
315 symp = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, 365 symp = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj,
316 in_plt); 366 in_plt);
317 if (symp != NULL && 367 if (symp != NULL &&
318 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 368 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
319 def = symp; 369 def = symp;
320 defobj = obj; 370 defobj = obj;
321 } 371 }
322 } 372 }
323 373
324 /* Search all RTLD_GLOBAL objects. */ 374 /* Search all RTLD_GLOBAL objects. */
325 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { 375 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) {
326 rdbg(("search _rtld_list_global for %s", name)); 376 rdbg(("search _rtld_list_global for %s", name));
327 symp = _rtld_symlook_list(name, hash, &_rtld_list_global, 377 symp = _rtld_symlook_list(name, hash, &_rtld_list_global,
328 &obj, in_plt); 378 &obj, in_plt);
329 if (symp != NULL && 379 if (symp != NULL &&
330 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 380 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
331 def = symp; 381 def = symp;
332 defobj = obj; 382 defobj = obj;
333 } 383 }
334 } 384 }
335  385
336 /* Search all dlopened DAGs containing the referencing object. */ 386 /* Search all dlopened DAGs containing the referencing object. */
337 SIMPLEQ_FOREACH(elm, &refobj->dldags, link) { 387 SIMPLEQ_FOREACH(elm, &refobj->dldags, link) {
338 if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK) 388 if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK)
339 break; 389 break;
340 rdbg(("search DAG with root %p (%s) for %s", elm->obj, 390 rdbg(("search DAG with root %p (%s) for %s", elm->obj,
341 elm->obj->path, name)); 391 elm->obj->path, name));
342 symp = _rtld_symlook_list(name, hash, &elm->obj->dagmembers, 392 symp = _rtld_symlook_list(name, hash, &elm->obj->dagmembers,
343 &obj, in_plt); 393 &obj, in_plt);
344 if (symp != NULL && 394 if (symp != NULL &&
345 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { 395 (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
346 def = symp; 396 def = symp;
347 defobj = obj; 397 defobj = obj;
348 } 398 }
349 } 399 }
350 400
351 /* 401 /*
352 * Search the dynamic linker itself, and possibly resolve the 402 * Search the dynamic linker itself, and possibly resolve the
353 * symbol from there. This is how the application links to 403 * symbol from there. This is how the application links to
354 * dynamic linker services such as dlopen. Only the values listed 404 * dynamic linker services such as dlopen. Only the values listed
355 * in the "_rtld_exports" array can be resolved from the dynamic 405 * in the "_rtld_exports" array can be resolved from the dynamic
356 * linker. 406 * linker.
357 */ 407 */
358 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { 408 if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) {
359 rdbg(("Search the dynamic linker itself.")); 409 rdbg(("Search the dynamic linker itself."));
360 symp = _rtld_symlook_obj(name, hash, &_rtld_objself, in_plt); 410 symp = _rtld_symlook_obj(name, hash, &_rtld_objself, in_plt);
361 if (symp != NULL && _rtld_is_exported(symp)) { 411 if (symp != NULL && _rtld_is_exported(symp)) {
362 def = symp; 412 def = symp;
363 defobj = &_rtld_objself; 413 defobj = &_rtld_objself;
364 } 414 }
365 } 415 }
366 416
367 if (def != NULL) 417 if (def != NULL)
368 *defobj_out = defobj; 418 *defobj_out = defobj;
369 return def; 419 return def;
370} 420}