rtld.c revision 1.97 1 /* $NetBSD: rtld.c,v 1.97 2003/07/21 15:17:55 skrll Exp $ */
2
3 /*
4 * Copyright 1996 John D. Polstra.
5 * Copyright 1996 Matt Thomas <matt (at) 3am-software.com>
6 * Copyright 2002 Charles M. Hannum <root (at) ihack.net>
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by John Polstra.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 /*
36 * Dynamic linker for ELF.
37 *
38 * John Polstra <jdp (at) polstra.com>.
39 */
40
41 #include <err.h>
42 #include <errno.h>
43 #include <fcntl.h>
44 #include <stdarg.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <unistd.h>
49 #include <sys/param.h>
50 #include <sys/mman.h>
51 #include <dirent.h>
52
53 #include <ctype.h>
54
55 #include <dlfcn.h>
56 #include "debug.h"
57 #include "rtld.h"
58
59 #if !defined(lint)
60 #include "sysident.h"
61 #endif
62
63 /*
64 * Function declarations.
65 */
66 static void _rtld_init __P((caddr_t, caddr_t));
67 static void _rtld_exit __P((void));
68
69 Elf_Addr _rtld __P((Elf_Addr *, Elf_Addr));
70
71
72 /*
73 * Data declarations.
74 */
75 static char *error_message; /* Message for dlopen(), or NULL */
76
77 struct r_debug _rtld_debug; /* for GDB; */
78 bool _rtld_trust; /* False for setuid and setgid programs */
79 Obj_Entry *_rtld_objlist; /* Head of linked list of shared objects */
80 Obj_Entry **_rtld_objtail; /* Link field of last object in list */
81 Obj_Entry *_rtld_objmain; /* The main program shared object */
82 Obj_Entry _rtld_objself; /* The dynamic linker shared object */
83 char *_rtld_path = _PATH_RTLD;
84 Elf_Sym _rtld_sym_zero; /* For resolving undefined weak refs. */
85 int _rtld_pagesz; /* Page size, as provided by kernel */
86
87 Search_Path *_rtld_default_paths;
88 Search_Path *_rtld_paths;
89
90 Library_Xform *_rtld_xforms;
91
92 /*
93 * Global declarations normally provided by crt0.
94 */
95 char *__progname;
96 char **environ;
97
98 extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
99 extern Elf_Dyn _DYNAMIC;
100
101 static void _rtld_call_fini_functions __P((Obj_Entry *));
102 static void _rtld_call_init_functions __P((Obj_Entry *));
103 static Obj_Entry *_rtld_dlcheck __P((void *));
104 static void _rtld_init_dag __P((Obj_Entry *));
105 static void _rtld_init_dag1 __P((Obj_Entry *, Obj_Entry *));
106 static void _rtld_objlist_remove __P((Objlist *, Obj_Entry *));
107 static void _rtld_unload_object __P((Obj_Entry *, bool));
108 static void _rtld_unref_dag __P((Obj_Entry *));
109 static Obj_Entry *_rtld_obj_from_addr __P((const void *));
110
111 static void
112 _rtld_call_fini_functions(first)
113 Obj_Entry *first;
114 {
115 Obj_Entry *obj;
116
117 for (obj = first; obj != NULL; obj = obj->next)
118 if (obj->fini != NULL)
119 (*obj->fini)();
120 }
121
122 static void
123 _rtld_call_init_functions(first)
124 Obj_Entry *first;
125 {
126
127 if (first != NULL) {
128 _rtld_call_init_functions(first->next);
129 if (first->init != NULL)
130 (*first->init)();
131 }
132 }
133
134 /*
135 * Initialize the dynamic linker. The argument is the address at which
136 * the dynamic linker has been mapped into memory. The primary task of
137 * this function is to relocate the dynamic linker.
138 */
139 static void
140 _rtld_init(mapbase, relocbase)
141 caddr_t mapbase, relocbase;
142 {
143
144 /* Conjure up an Obj_Entry structure for the dynamic linker. */
145 _rtld_objself.path = _rtld_path;
146 _rtld_objself.pathlen = strlen(_rtld_path);
147 _rtld_objself.rtld = true;
148 _rtld_objself.mapbase = mapbase;
149 _rtld_objself.relocbase = relocbase;
150 _rtld_objself.dynamic = (Elf_Dyn *) &_DYNAMIC;
151
152 #ifdef RTLD_RELOCATE_SELF
153 #error platform still uses RTLD_RELOCATE_SELF
154 #endif
155
156 _rtld_digest_dynamic(&_rtld_objself);
157 assert(!_rtld_objself.needed && !_rtld_objself.pltrel &&
158 !_rtld_objself.pltrela);
159 #if !defined(__arm__) && !defined(__mips__) && !defined(__sh__)
160 /* ARM, MIPS and SH{3,5} have a bogus DT_TEXTREL. */
161 assert(!_rtld_objself.pltgot && !_rtld_objself.textrel);
162 #endif
163
164 _rtld_add_paths(&_rtld_default_paths, RTLD_DEFAULT_LIBRARY_PATH);
165
166 /*
167 * Set up the _rtld_objlist pointer, so that rtld symbols can be found.
168 */
169 _rtld_objlist = &_rtld_objself;
170
171 /* Make the object list empty again. */
172 _rtld_objlist = NULL;
173 _rtld_objtail = &_rtld_objlist;
174
175 _rtld_debug.r_brk = _rtld_debug_state;
176 _rtld_debug.r_state = RT_CONSISTENT;
177 }
178
179 /*
180 * Cleanup procedure. It will be called (by the atexit() mechanism) just
181 * before the process exits.
182 */
183 static void
184 _rtld_exit()
185 {
186
187 dbg(("rtld_exit()"));
188
189 _rtld_call_fini_functions(_rtld_objlist->next);
190 }
191
192 /*
193 * Main entry point for dynamic linking. The argument is the stack
194 * pointer. The stack is expected to be laid out as described in the
195 * SVR4 ABI specification, Intel 386 Processor Supplement. Specifically,
196 * the stack pointer points to a word containing ARGC. Following that
197 * in the stack is a null-terminated sequence of pointers to argument
198 * strings. Then comes a null-terminated sequence of pointers to
199 * environment strings. Finally, there is a sequence of "auxiliary
200 * vector" entries.
201 *
202 * This function returns the entry point for the main program, the dynamic
203 * linker's exit procedure in sp[0], and a pointer to the main object in
204 * sp[1].
205 */
206 Elf_Addr
207 _rtld(sp, relocbase)
208 Elf_Addr *sp;
209 Elf_Addr relocbase;
210 {
211 const AuxInfo *pAUX_base, *pAUX_entry, *pAUX_execfd, *pAUX_phdr,
212 *pAUX_phent, *pAUX_phnum, *pAUX_euid, *pAUX_egid,
213 *pAUX_ruid, *pAUX_rgid;
214 const AuxInfo *pAUX_pagesz;
215 char **env;
216 const AuxInfo *aux;
217 const AuxInfo *auxp;
218 Elf_Addr *const osp = sp;
219 bool bind_now = 0;
220 const char *ld_bind_now;
221 const char **argv;
222 long argc;
223 const char **real___progname;
224 const Obj_Entry **real___mainprog_obj;
225 char ***real_environ;
226 #if defined(RTLD_DEBUG)
227 int i = 0;
228 #endif
229
230 /*
231 * On entry, the dynamic linker itself has not been relocated yet.
232 * Be very careful not to reference any global data until after
233 * _rtld_init has returned. It is OK to reference file-scope statics
234 * and string constants, and to call static and global functions.
235 */
236 /* Find the auxiliary vector on the stack. */
237 /* first Elf_Word reserved to address of exit routine */
238 #if defined(RTLD_DEBUG)
239 debug = 1;
240 dbg(("sp = %p, argc = %ld, argv = %p <%s> relocbase %p", sp,
241 (long)sp[2], &sp[3], (char *) sp[3], (void *)relocbase));
242 dbg(("got is at %p, dynamic is at %p", _GLOBAL_OFFSET_TABLE_,
243 &_DYNAMIC));
244 dbg(("_ctype_ is %p", _ctype_));
245 #endif
246
247 sp += 2; /* skip over return argument space */
248 argv = (const char **) &sp[1];
249 argc = *(long *)sp;
250 sp += 2 + argc; /* Skip over argc, arguments, and NULL
251 * terminator */
252 env = (char **) sp;
253 while (*sp++ != 0) { /* Skip over environment, and NULL terminator */
254 #if defined(RTLD_DEBUG)
255 dbg(("env[%d] = %p %s", i++, (void *)sp[-1], (char *)sp[-1]));
256 #endif
257 }
258 aux = (const AuxInfo *) sp;
259
260 pAUX_base = pAUX_entry = pAUX_execfd = NULL;
261 pAUX_phdr = pAUX_phent = pAUX_phnum = NULL;
262 pAUX_euid = pAUX_ruid = pAUX_egid = pAUX_rgid = NULL;
263 pAUX_pagesz = NULL;
264
265 /* Digest the auxiliary vector. */
266 for (auxp = aux; auxp->a_type != AT_NULL; ++auxp) {
267 switch (auxp->a_type) {
268 case AT_BASE:
269 pAUX_base = auxp;
270 break;
271 case AT_ENTRY:
272 pAUX_entry = auxp;
273 break;
274 case AT_EXECFD:
275 pAUX_execfd = auxp;
276 break;
277 case AT_PHDR:
278 pAUX_phdr = auxp;
279 break;
280 case AT_PHENT:
281 pAUX_phent = auxp;
282 break;
283 case AT_PHNUM:
284 pAUX_phnum = auxp;
285 break;
286 #ifdef AT_EUID
287 case AT_EUID:
288 pAUX_euid = auxp;
289 break;
290 case AT_RUID:
291 pAUX_ruid = auxp;
292 break;
293 case AT_EGID:
294 pAUX_egid = auxp;
295 break;
296 case AT_RGID:
297 pAUX_rgid = auxp;
298 break;
299 #endif
300 case AT_PAGESZ:
301 pAUX_pagesz = auxp;
302 break;
303 }
304 }
305
306 /* Initialize and relocate ourselves. */
307 if (pAUX_base == NULL) {
308 _rtld_error("Bad pAUX_base");
309 _rtld_die();
310 }
311 assert(pAUX_pagesz != NULL);
312 _rtld_pagesz = (int)pAUX_pagesz->a_v;
313 _rtld_init((caddr_t)pAUX_base->a_v, (caddr_t)relocbase);
314
315 __progname = _rtld_objself.path;
316 environ = env;
317
318 _rtld_trust = ((pAUX_euid ? (uid_t)pAUX_euid->a_v : geteuid()) ==
319 (pAUX_ruid ? (uid_t)pAUX_ruid->a_v : getuid())) &&
320 ((pAUX_egid ? (gid_t)pAUX_egid->a_v : getegid()) ==
321 (pAUX_rgid ? (gid_t)pAUX_rgid->a_v : getgid()));
322
323 ld_bind_now = getenv("LD_BIND_NOW");
324 if (ld_bind_now != NULL && *ld_bind_now != '\0')
325 bind_now = true;
326 if (_rtld_trust) {
327 #ifdef DEBUG
328 const char *ld_debug = getenv("LD_DEBUG");
329 #ifdef RTLD_DEBUG
330 debug = 0;
331 #endif
332 if (ld_debug != NULL && *ld_debug != '\0')
333 debug = 1;
334 #endif
335 _rtld_add_paths(&_rtld_paths, getenv("LD_LIBRARY_PATH"));
336 }
337 _rtld_process_hints(&_rtld_paths, &_rtld_xforms, _PATH_LD_HINTS);
338 dbg(("dynamic linker is initialized, mapbase=%p, relocbase=%p",
339 _rtld_objself.mapbase, _rtld_objself.relocbase));
340
341 /*
342 * Load the main program, or process its program header if it is
343 * already loaded.
344 */
345 if (pAUX_execfd != NULL) { /* Load the main program. */
346 int fd = pAUX_execfd->a_v;
347 dbg(("loading main program"));
348 _rtld_objmain = _rtld_map_object(xstrdup(argv[0] ? argv[0] :
349 "main program"), fd, NULL);
350 close(fd);
351 if (_rtld_objmain == NULL)
352 _rtld_die();
353 } else { /* Main program already loaded. */
354 const Elf_Phdr *phdr;
355 int phnum;
356 caddr_t entry;
357
358 dbg(("processing main program's program header"));
359 assert(pAUX_phdr != NULL);
360 phdr = (const Elf_Phdr *) pAUX_phdr->a_v;
361 assert(pAUX_phnum != NULL);
362 phnum = pAUX_phnum->a_v;
363 assert(pAUX_phent != NULL);
364 assert(pAUX_phent->a_v == sizeof(Elf_Phdr));
365 assert(pAUX_entry != NULL);
366 entry = (caddr_t) pAUX_entry->a_v;
367 _rtld_objmain = _rtld_digest_phdr(phdr, phnum, entry);
368 _rtld_objmain->path = xstrdup(argv[0] ? argv[0] :
369 "main program");
370 _rtld_objmain->pathlen = strlen(_rtld_objmain->path);
371 }
372
373 _rtld_objmain->mainprog = true;
374
375 /*
376 * Get the actual dynamic linker pathname from the executable if
377 * possible. (It should always be possible.) That ensures that
378 * gdb will find the right dynamic linker even if a non-standard
379 * one is being used.
380 */
381 if (_rtld_objmain->interp != NULL &&
382 strcmp(_rtld_objmain->interp, _rtld_objself.path) != 0)
383 _rtld_objself.path = xstrdup(_rtld_objmain->interp);
384 dbg(("actual dynamic linker is %s", _rtld_objself.path));
385
386 _rtld_digest_dynamic(_rtld_objmain);
387
388 /* Link the main program into the list of objects. */
389 *_rtld_objtail = _rtld_objmain;
390 _rtld_objtail = &_rtld_objmain->next;
391
392 _rtld_linkmap_add(_rtld_objmain);
393 _rtld_linkmap_add(&_rtld_objself);
394
395 ++_rtld_objmain->refcount;
396 _rtld_objmain->mainref = 1;
397 _rtld_objlist_add(&_rtld_list_main, _rtld_objmain);
398
399 /* Initialize a fake symbol for resolving undefined weak references. */
400 _rtld_sym_zero.st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE);
401 _rtld_sym_zero.st_shndx = SHN_ABS;
402
403 /*
404 * Pre-load user-specified objects after the main program but before
405 * any shared object dependencies.
406 */
407 dbg(("preloading objects"));
408 if (_rtld_trust && _rtld_preload(getenv("LD_PRELOAD")) == -1)
409 _rtld_die();
410
411 dbg(("loading needed objects"));
412 if (_rtld_load_needed_objects(_rtld_objmain, RTLD_MAIN) == -1)
413 _rtld_die();
414
415 dbg(("relocating objects"));
416 if (_rtld_relocate_objects(_rtld_objmain, bind_now) == -1)
417 _rtld_die();
418
419 dbg(("doing copy relocations"));
420 if (_rtld_do_copy_relocations(_rtld_objmain) == -1)
421 _rtld_die();
422
423 /*
424 * Set the __progname, environ and, __mainprog_obj before
425 * calling anything that might use them.
426 */
427 real___progname = _rtld_objmain_sym("__progname");
428 if (real___progname) {
429 if (argv[0] != NULL) {
430 if ((*real___progname = strrchr(argv[0], '/')) == NULL)
431 (*real___progname) = argv[0];
432 else
433 (*real___progname)++;
434 } else {
435 (*real___progname) = NULL;
436 }
437 }
438 real_environ = _rtld_objmain_sym("environ");
439 if (real_environ)
440 *real_environ = environ;
441 real___mainprog_obj = _rtld_objmain_sym("__mainprog_obj");
442 if (real___mainprog_obj)
443 *real___mainprog_obj = _rtld_objmain;
444
445 dbg(("calling _init functions"));
446 _rtld_call_init_functions(_rtld_objmain->next);
447
448 dbg(("control at program entry point = %p, obj = %p, exit = %p",
449 _rtld_objmain->entry, _rtld_objmain, _rtld_exit));
450
451 /*
452 * Return with the entry point and the exit procedure in at the top
453 * of stack.
454 */
455
456 _rtld_debug_state(); /* say hello to gdb! */
457
458 ((void **) osp)[0] = _rtld_exit;
459 ((void **) osp)[1] = _rtld_objmain;
460 return (Elf_Addr) _rtld_objmain->entry;
461 }
462
463 void
464 _rtld_die()
465 {
466 const char *msg = _rtld_dlerror();
467
468 if (msg == NULL)
469 msg = "Fatal error";
470 xerrx(1, "%s", msg);
471 }
472
473 static Obj_Entry *
474 _rtld_dlcheck(handle)
475 void *handle;
476 {
477 Obj_Entry *obj;
478
479 for (obj = _rtld_objlist; obj != NULL; obj = obj->next)
480 if (obj == (Obj_Entry *) handle)
481 break;
482
483 if (obj == NULL || obj->dl_refcount == 0) {
484 xwarnx("Invalid shared object handle %p", handle);
485 return NULL;
486 }
487 return obj;
488 }
489
490 static void
491 _rtld_init_dag(root)
492 Obj_Entry *root;
493 {
494
495 _rtld_init_dag1(root, root);
496 }
497
498 static void
499 _rtld_init_dag1(root, obj)
500 Obj_Entry *root;
501 Obj_Entry *obj;
502 {
503 const Needed_Entry *needed;
504
505 if (!obj->mainref) {
506 if (_rtld_objlist_find(&obj->dldags, root))
507 return;
508 rdbg(("add %p (%s) to %p (%s) DAG", obj, obj->path, root,
509 root->path));
510 _rtld_objlist_add(&obj->dldags, root);
511 _rtld_objlist_add(&root->dagmembers, obj);
512 }
513 for (needed = obj->needed; needed != NULL; needed = needed->next)
514 if (needed->obj != NULL)
515 _rtld_init_dag1(root, needed->obj);
516 }
517
518 /*
519 * Note, this is called only for objects loaded by dlopen().
520 */
521 static void
522 _rtld_unload_object(root, do_fini_funcs)
523 Obj_Entry *root;
524 bool do_fini_funcs;
525 {
526
527 _rtld_unref_dag(root);
528 if (root->refcount == 0) { /* We are finished with some objects. */
529 Obj_Entry *obj;
530 Obj_Entry **linkp;
531 Objlist_Entry *elm;
532
533 /* Finalize objects that are about to be unmapped. */
534 if (do_fini_funcs)
535 for (obj = _rtld_objlist->next; obj != NULL; obj = obj->next)
536 if (obj->refcount == 0 && obj->fini != NULL)
537 (*obj->fini)();
538
539 /* Remove the DAG from all objects' DAG lists. */
540 SIMPLEQ_FOREACH(elm, &root->dagmembers, link)
541 _rtld_objlist_remove(&elm->obj->dldags, root);
542
543 /* Remove the DAG from the RTLD_GLOBAL list. */
544 if (root->globalref) {
545 root->globalref = 0;
546 _rtld_objlist_remove(&_rtld_list_global, root);
547 }
548
549 /* Unmap all objects that are no longer referenced. */
550 linkp = &_rtld_objlist->next;
551 while ((obj = *linkp) != NULL) {
552 if (obj->refcount == 0) {
553 #ifdef RTLD_DEBUG
554 dbg(("unloading \"%s\"", obj->path));
555 #endif
556 munmap(obj->mapbase, obj->mapsize);
557 _rtld_objlist_remove(&_rtld_list_global, obj);
558 _rtld_linkmap_delete(obj);
559 *linkp = obj->next;
560 _rtld_obj_free(obj);
561 } else
562 linkp = &obj->next;
563 }
564 _rtld_objtail = linkp;
565 }
566 }
567
568 static void
569 _rtld_unref_dag(root)
570 Obj_Entry *root;
571 {
572
573 assert(root);
574 assert(root->refcount != 0);
575 --root->refcount;
576 if (root->refcount == 0) {
577 const Needed_Entry *needed;
578
579 for (needed = root->needed; needed != NULL;
580 needed = needed->next) {
581 if (needed->obj != NULL)
582 _rtld_unref_dag(needed->obj);
583 }
584 }
585 }
586
587 int
588 _rtld_dlclose(handle)
589 void *handle;
590 {
591 Obj_Entry *root = _rtld_dlcheck(handle);
592
593 if (root == NULL)
594 return -1;
595
596 _rtld_debug.r_state = RT_DELETE;
597 _rtld_debug_state();
598
599 --root->dl_refcount;
600 _rtld_unload_object(root, true);
601
602 _rtld_debug.r_state = RT_CONSISTENT;
603 _rtld_debug_state();
604
605 return 0;
606 }
607
608 char *
609 _rtld_dlerror()
610 {
611 char *msg = error_message;
612
613 error_message = NULL;
614 return msg;
615 }
616
617 void *
618 _rtld_dlopen(name, mode)
619 const char *name;
620 int mode;
621 {
622 Obj_Entry **old_obj_tail = _rtld_objtail;
623 Obj_Entry *obj = NULL;
624
625 _rtld_debug.r_state = RT_ADD;
626 _rtld_debug_state();
627
628 if (name == NULL) {
629 obj = _rtld_objmain;
630 obj->refcount++;
631 } else
632 obj = _rtld_load_library(name, _rtld_objmain, mode);
633
634 if (obj != NULL) {
635 ++obj->dl_refcount;
636 if (*old_obj_tail != NULL) { /* We loaded something new. */
637 assert(*old_obj_tail == obj);
638
639 if (_rtld_load_needed_objects(obj, mode) == -1 ||
640 (_rtld_init_dag(obj),
641 _rtld_relocate_objects(obj,
642 ((mode & 3) == RTLD_NOW))) == -1) {
643 _rtld_unload_object(obj, false);
644 obj->dl_refcount--;
645 obj = NULL;
646 } else
647 _rtld_call_init_functions(obj);
648 }
649 }
650 _rtld_debug.r_state = RT_CONSISTENT;
651 _rtld_debug_state();
652
653 return obj;
654 }
655
656 /*
657 * Find a symbol in the main program.
658 */
659 void *
660 _rtld_objmain_sym(name)
661 const char *name;
662 {
663 unsigned long hash;
664 const Elf_Sym *def;
665 const Obj_Entry *obj;
666
667 hash = _rtld_elf_hash(name);
668 obj = _rtld_objmain;
669
670 def = _rtld_symlook_list(name, hash, &_rtld_list_main, &obj, false);
671
672 if (def != NULL)
673 return obj->relocbase + def->st_value;
674 return(NULL);
675 }
676
677 void *
678 _rtld_dlsym(handle, name)
679 void *handle;
680 const char *name;
681 {
682 const Obj_Entry *obj;
683 unsigned long hash;
684 const Elf_Sym *def;
685 const Obj_Entry *defobj;
686 void *retaddr;
687
688 hash = _rtld_elf_hash(name);
689 def = NULL;
690 defobj = NULL;
691
692 switch ((intptr_t)handle) {
693 case (intptr_t)NULL:
694 case (intptr_t)RTLD_NEXT:
695 case (intptr_t)RTLD_DEFAULT:
696 case (intptr_t)RTLD_SELF:
697 retaddr = __builtin_return_address(0); /* __GNUC__ only */
698 if ((obj = _rtld_obj_from_addr(retaddr)) == NULL) {
699 _rtld_error("Cannot determine caller's shared object");
700 return NULL;
701 }
702
703 switch ((intptr_t)handle) {
704 case (intptr_t)NULL: /* Just the caller's shared object. */
705 def = _rtld_symlook_obj(name, hash, obj, false);
706 defobj = obj;
707 break;
708
709 case (intptr_t)RTLD_NEXT: /* Objects after callers */
710 obj = obj->next;
711 /*FALLTHROUGH*/
712
713 case (intptr_t)RTLD_SELF: /* Caller included */
714 for (; obj; obj = obj->next) {
715 if ((def = _rtld_symlook_obj(name, hash, obj,
716 false)) != NULL) {
717 defobj = obj;
718 break;
719 }
720 }
721 break;
722
723 case (intptr_t)RTLD_DEFAULT:
724 def = _rtld_symlook_default(name, hash, obj, &defobj,
725 false);
726 break;
727
728 default:
729 abort();
730 }
731 break;
732
733 default:
734 if ((obj = _rtld_dlcheck(handle)) == NULL)
735 return NULL;
736
737 if (obj->mainprog) {
738 /* Search main program and all libraries loaded by it */
739 def = _rtld_symlook_list(name, hash, &_rtld_list_main,
740 &defobj, false);
741 } else {
742 /*
743 * XXX - This isn't correct. The search should include
744 * the whole DAG rooted at the given object.
745 */
746 def = _rtld_symlook_obj(name, hash, obj, false);
747 defobj = obj;
748 }
749 break;
750 }
751
752 if (def != NULL) {
753 #ifdef __HAVE_FUNCTION_DESCRIPTORS
754 if (ELF_ST_TYPE(def->st_info) == STT_FUNC)
755 return (void *)_rtld_function_descriptor_alloc(defobj,
756 def, 0);
757 #endif /* __HAVE_FUNCTION_DESCRIPTORS */
758 return defobj->relocbase + def->st_value;
759 }
760
761 _rtld_error("Undefined symbol \"%s\"", name);
762 return NULL;
763 }
764
765 int
766 _rtld_dladdr(addr, info)
767 const void *addr;
768 Dl_info *info;
769 {
770 const Obj_Entry *obj;
771 const Elf_Sym *def, *best_def;
772 void *symbol_addr;
773 unsigned long symoffset;
774
775 #ifdef __HAVE_FUNCTION_DESCRIPTORS
776 addr = _rtld_function_descriptor_function(addr);
777 #endif /* __HAVE_FUNCTION_DESCRIPTORS */
778
779 obj = _rtld_obj_from_addr(addr);
780 if (obj == NULL) {
781 _rtld_error("No shared object contains address");
782 return 0;
783 }
784 info->dli_fname = obj->path;
785 info->dli_fbase = obj->mapbase;
786 info->dli_saddr = (void *)0;
787 info->dli_sname = NULL;
788
789 /*
790 * Walk the symbol list looking for the symbol whose address is
791 * closest to the address sent in.
792 */
793 best_def = NULL;
794 for (symoffset = 0; symoffset < obj->nchains; symoffset++) {
795 def = obj->symtab + symoffset;
796
797 /*
798 * For skip the symbol if st_shndx is either SHN_UNDEF or
799 * SHN_COMMON.
800 */
801 if (def->st_shndx == SHN_UNDEF || def->st_shndx == SHN_COMMON)
802 continue;
803
804 /*
805 * If the symbol is greater than the specified address, or if it
806 * is further away from addr than the current nearest symbol,
807 * then reject it.
808 */
809 symbol_addr = obj->relocbase + def->st_value;
810 if (symbol_addr > addr || symbol_addr < info->dli_saddr)
811 continue;
812
813 /* Update our idea of the nearest symbol. */
814 info->dli_sname = obj->strtab + def->st_name;
815 info->dli_saddr = symbol_addr;
816 best_def = def;
817
818 /* Exact match? */
819 if (info->dli_saddr == addr)
820 break;
821 }
822
823 #ifdef __HAVE_FUNCTION_DESCRIPTORS
824 if (best_def != NULL && ELF_ST_TYPE(best_def->st_info) == STT_FUNC)
825 info->dli_saddr = (void *)_rtld_function_descriptor_alloc(obj,
826 best_def, 0);
827 #endif /* __HAVE_FUNCTION_DESCRIPTORS */
828
829 return 1;
830 }
831
832 /*
833 * Error reporting function. Use it like printf. If formats the message
834 * into a buffer, and sets things up so that the next call to dlerror()
835 * will return the message.
836 */
837 void
838 _rtld_error(const char *fmt,...)
839 {
840 static char buf[512];
841 va_list ap;
842
843 va_start(ap, fmt);
844 xvsnprintf(buf, sizeof buf, fmt, ap);
845 error_message = buf;
846 va_end(ap);
847 }
848
849 void
850 _rtld_debug_state()
851 {
852
853 /* do nothing */
854 }
855
856 void
857 _rtld_linkmap_add(obj)
858 Obj_Entry *obj;
859 {
860 struct link_map *l = &obj->linkmap;
861 struct link_map *prev;
862
863 obj->linkmap.l_name = obj->path;
864 obj->linkmap.l_addr = obj->relocbase;
865 obj->linkmap.l_ld = obj->dynamic;
866 #ifdef __mips__
867 /* XXX This field is not standard and will be removed eventually. */
868 obj->linkmap.l_offs = obj->relocbase;
869 #endif
870
871 if (_rtld_debug.r_map == NULL) {
872 _rtld_debug.r_map = l;
873 return;
874 }
875 for (prev = _rtld_debug.r_map; prev->l_next != NULL; prev = prev->l_next);
876 l->l_prev = prev;
877 prev->l_next = l;
878 l->l_next = NULL;
879 }
880
881 void
882 _rtld_linkmap_delete(obj)
883 Obj_Entry *obj;
884 {
885 struct link_map *l = &obj->linkmap;
886
887 if (l->l_prev == NULL) {
888 if ((_rtld_debug.r_map = l->l_next) != NULL)
889 l->l_next->l_prev = NULL;
890 return;
891 }
892 if ((l->l_prev->l_next = l->l_next) != NULL)
893 l->l_next->l_prev = l->l_prev;
894 }
895
896 static Obj_Entry *
897 _rtld_obj_from_addr(const void *addr)
898 {
899 Obj_Entry *obj;
900
901 for (obj = _rtld_objlist; obj != NULL; obj = obj->next) {
902 if (addr < (void *) obj->mapbase)
903 continue;
904 if (addr < (void *) (obj->mapbase + obj->mapsize))
905 return obj;
906 }
907 return NULL;
908 }
909
910 static void
911 _rtld_objlist_remove(list, obj)
912 Objlist *list;
913 Obj_Entry *obj;
914 {
915 Objlist_Entry *elm;
916
917 if ((elm = _rtld_objlist_find(list, obj)) != NULL) {
918 SIMPLEQ_REMOVE(list, elm, Struct_Objlist_Entry, link);
919 free(elm);
920 }
921 }
922