Home | History | Annotate | Line # | Download | only in ld.elf_so
rtld.c revision 1.5.2.1
      1  1.5.2.1  mycroft /*	$NetBSD: rtld.c,v 1.5.2.1 1998/05/08 17:39:12 mycroft Exp $	*/
      2      1.1      cgd 
      3      1.1      cgd /*
      4      1.1      cgd  * Copyright 1996 John D. Polstra.
      5      1.1      cgd  * Copyright 1996 Matt Thomas <matt (at) 3am-software.com>
      6      1.1      cgd  * All rights reserved.
      7      1.1      cgd  *
      8      1.1      cgd  * Redistribution and use in source and binary forms, with or without
      9      1.1      cgd  * modification, are permitted provided that the following conditions
     10      1.1      cgd  * are met:
     11      1.1      cgd  * 1. Redistributions of source code must retain the above copyright
     12      1.1      cgd  *    notice, this list of conditions and the following disclaimer.
     13      1.1      cgd  * 2. Redistributions in binary form must reproduce the above copyright
     14      1.1      cgd  *    notice, this list of conditions and the following disclaimer in the
     15      1.1      cgd  *    documentation and/or other materials provided with the distribution.
     16      1.1      cgd  * 3. All advertising materials mentioning features or use of this software
     17      1.1      cgd  *    must display the following acknowledgement:
     18      1.1      cgd  *      This product includes software developed by John Polstra.
     19      1.1      cgd  * 4. The name of the author may not be used to endorse or promote products
     20      1.1      cgd  *    derived from this software without specific prior written permission.
     21      1.1      cgd  *
     22      1.1      cgd  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     23      1.1      cgd  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24      1.1      cgd  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25      1.1      cgd  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     26      1.1      cgd  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     27      1.1      cgd  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28      1.1      cgd  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29      1.1      cgd  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30      1.1      cgd  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     31      1.1      cgd  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32      1.1      cgd  */
     33      1.1      cgd 
     34      1.1      cgd /*
     35      1.1      cgd  * Dynamic linker for ELF.
     36      1.1      cgd  *
     37      1.1      cgd  * John Polstra <jdp (at) polstra.com>.
     38      1.1      cgd  */
     39      1.1      cgd 
     40      1.1      cgd #include <err.h>
     41      1.1      cgd #include <errno.h>
     42      1.1      cgd #include <fcntl.h>
     43      1.1      cgd #include <stdarg.h>
     44      1.1      cgd #include <stdio.h>
     45      1.1      cgd #include <stdlib.h>
     46      1.1      cgd #include <string.h>
     47      1.1      cgd #include <unistd.h>
     48      1.3      cgd #include <sys/param.h>
     49      1.1      cgd #include <sys/mman.h>
     50      1.1      cgd #include <dirent.h>
     51      1.1      cgd 
     52      1.1      cgd #include <ctype.h>
     53      1.1      cgd 
     54      1.2      cgd #include <dlfcn.h>
     55      1.1      cgd #include "debug.h"
     56      1.1      cgd #include "rtld.h"
     57      1.3      cgd 
     58      1.3      cgd #include "sysident.h"
     59      1.1      cgd 
     60      1.2      cgd #ifndef RTLD_NOW
     61      1.2      cgd #define	RTLD_NOW	(RTLD_LAZY + 1)
     62      1.2      cgd #endif
     63      1.1      cgd 
     64      1.1      cgd /*
     65      1.1      cgd  * Debugging support.
     66      1.1      cgd  */
     67      1.1      cgd 
     68      1.1      cgd typedef void (*funcptr)(void);
     69      1.1      cgd 
     70      1.1      cgd /*
     71      1.1      cgd  * Function declarations.
     72      1.1      cgd  */
     73      1.1      cgd static void _rtld_init(caddr_t);
     74      1.1      cgd static void _rtld_exit(void);
     75      1.1      cgd 
     76      1.1      cgd /*
     77      1.1      cgd  * Data declarations.
     78      1.1      cgd  */
     79      1.1      cgd static char *error_message;	/* Message for dlopen(), or NULL */
     80      1.1      cgd 
     81      1.1      cgd struct r_debug _rtld_debug;	/* for GDB; */
     82      1.1      cgd bool _rtld_trust;		/* False for setuid and setgid programs */
     83      1.1      cgd Obj_Entry *_rtld_objlist;	/* Head of linked list of shared objects */
     84      1.1      cgd Obj_Entry **_rtld_objtail;	/* Link field of last object in list */
     85      1.1      cgd Obj_Entry *_rtld_objmain;	/* The main program shared object */
     86      1.1      cgd Obj_Entry _rtld_objself;	/* The dynamic linker shared object */
     87      1.4      cgd char _rtld_path[] = _PATH_RTLD;
     88      1.1      cgd 
     89      1.1      cgd Search_Path *_rtld_paths;
     90      1.1      cgd /*
     91      1.1      cgd  * Global declarations normally provided by crt0.
     92      1.1      cgd  */
     93      1.1      cgd char *__progname;
     94      1.1      cgd char **environ;
     95      1.1      cgd 
     96      1.1      cgd #ifdef OLD_GOT
     97      1.1      cgd extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
     98      1.1      cgd #else
     99      1.1      cgd extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
    100      1.1      cgd extern Elf_Dyn _DYNAMIC;
    101      1.1      cgd #endif
    102      1.1      cgd 
    103      1.1      cgd static void
    104      1.1      cgd _rtld_call_fini_functions(
    105      1.1      cgd     Obj_Entry *first)
    106      1.1      cgd {
    107      1.1      cgd     Obj_Entry *obj;
    108      1.1      cgd 
    109      1.1      cgd     for (obj = first;  obj != NULL;  obj = obj->next)
    110      1.1      cgd 	if (obj->fini != NULL)
    111      1.1      cgd 	    (*obj->fini)();
    112      1.1      cgd }
    113      1.1      cgd 
    114      1.1      cgd static void
    115      1.1      cgd _rtld_call_init_functions(
    116      1.1      cgd     Obj_Entry *first)
    117      1.1      cgd {
    118      1.1      cgd     if (first != NULL) {
    119      1.1      cgd 	_rtld_call_init_functions(first->next);
    120      1.1      cgd 	if (first->init != NULL)
    121      1.1      cgd 	    (*first->init)();
    122      1.1      cgd     }
    123      1.1      cgd }
    124      1.1      cgd 
    125      1.1      cgd /*
    127      1.1      cgd  * Initialize the dynamic linker.  The argument is the address at which
    128      1.1      cgd  * the dynamic linker has been mapped into memory.  The primary task of
    129      1.1      cgd  * this function is to relocate the dynamic linker.
    130      1.1      cgd  */
    131      1.1      cgd static void
    132      1.1      cgd _rtld_init(
    133      1.1      cgd     caddr_t mapbase)
    134      1.1      cgd {
    135      1.1      cgd     _rtld_add_paths(&_rtld_paths, RTLD_DEFAULT_LIBRARY_PATH);
    136      1.1      cgd 
    137      1.1      cgd     /* Conjure up an Obj_Entry structure for the dynamic linker. */
    138      1.4      cgd 
    139      1.1      cgd     _rtld_objself.path = _rtld_path;
    140      1.1      cgd     _rtld_objself.rtld = true;
    141  1.5.2.1  mycroft     _rtld_objself.mapbase = mapbase;
    142  1.5.2.1  mycroft #ifdef __mips__
    143  1.5.2.1  mycroft     /* mips ld.so currently linked at load address, so no relocation needed */
    144  1.5.2.1  mycroft     _rtld_objself.relocbase = 0;
    145      1.1      cgd #else
    146  1.5.2.1  mycroft     _rtld_objself.relocbase = mapbase;
    147      1.1      cgd #endif
    148      1.1      cgd     _rtld_objself.pltgot = NULL;
    149      1.1      cgd #ifdef OLD_GOT
    150      1.1      cgd     _rtld_objself.dynamic = (Elf_Dyn *) _GLOBAL_OFFSET_TABLE_[0];
    151      1.1      cgd #else
    152      1.1      cgd     _rtld_objself.dynamic = &_DYNAMIC;
    153      1.1      cgd #endif
    154      1.1      cgd 
    155      1.1      cgd     _rtld_digest_dynamic(&_rtld_objself);
    156      1.1      cgd #ifdef __alpha__
    157      1.1      cgd /* XXX XXX XXX */
    158      1.1      cgd _rtld_objself.pltgot = NULL;
    159      1.1      cgd #endif
    160  1.5.2.1  mycroft     assert(_rtld_objself.needed == NULL);
    161      1.1      cgd #ifndef __mips__	/* no relocation for mips */
    162  1.5.2.1  mycroft     assert(!_rtld_objself.textrel);
    163      1.1      cgd #endif
    164      1.1      cgd 
    165      1.1      cgd     /* Set up the _rtld_objlist pointer, so that rtld symbols can be found. */
    166      1.1      cgd     _rtld_objlist = &_rtld_objself;
    167      1.1      cgd 
    168      1.1      cgd     _rtld_relocate_objects(&_rtld_objself, true);
    169      1.1      cgd 
    170      1.1      cgd     /* Make the object list empty again. */
    171      1.1      cgd     _rtld_objlist = NULL;
    172      1.1      cgd     _rtld_objtail = &_rtld_objlist;
    173      1.1      cgd 
    174      1.1      cgd     _rtld_debug.r_brk = _rtld_debug_state;
    175      1.1      cgd     _rtld_debug.r_state = RT_CONSISTENT;
    176      1.1      cgd }
    177      1.1      cgd 
    178      1.1      cgd /*
    180      1.1      cgd  * Cleanup procedure.  It will be called (by the atexit() mechanism) just
    181      1.1      cgd  * before the process exits.
    182      1.1      cgd  */
    183      1.1      cgd static void
    184      1.1      cgd _rtld_exit(void)
    185      1.1      cgd {
    186      1.1      cgd     dbg("rtld_exit()");
    187      1.1      cgd 
    188      1.1      cgd     _rtld_call_fini_functions(_rtld_objlist->next);
    189      1.1      cgd }
    190      1.1      cgd 
    191      1.1      cgd /*
    193      1.1      cgd  * Main entry point for dynamic linking.  The argument is the stack
    194      1.1      cgd  * pointer.  The stack is expected to be laid out as described in the
    195      1.1      cgd  * SVR4 ABI specification, Intel 386 Processor Supplement.  Specifically,
    196      1.1      cgd  * the stack pointer points to a word containing ARGC.  Following that
    197      1.1      cgd  * in the stack is a null-terminated sequence of pointers to argument
    198      1.1      cgd  * strings.  Then comes a null-terminated sequence of pointers to
    199      1.1      cgd  * environment strings.  Finally, there is a sequence of "auxiliary
    200      1.1      cgd  * vector" entries.
    201      1.1      cgd  *
    202      1.1      cgd  * This function returns the entry point for the main program in %eax,
    203      1.1      cgd  * and the dynamic linker's exit procedure in %edx.  We accomplish this
    204      1.1      cgd  * by declaring the return value to have the 64-bit type "long long".
    205      1.5      mrg  * Such values are returned with their most-significant 32 bits in %edx,
    206      1.5      mrg  * and their least-significant 32 bits in %eax.
    207      1.1      cgd  */
    208      1.1      cgd Elf_Addr _rtld(Elf_Word *);
    209      1.1      cgd 
    210      1.1      cgd Elf_Addr
    211      1.1      cgd _rtld(
    212      1.1      cgd     Elf_Word *sp)
    213      1.1      cgd {
    214      1.1      cgd     const AuxInfo *aux_info[AUX_count];
    215      1.1      cgd     int i = 0;
    216      1.1      cgd     char **env;
    217      1.1      cgd     const AuxInfo *aux;
    218      1.1      cgd     const AuxInfo *auxp;
    219      1.1      cgd     Elf_Word * const osp = sp;
    220      1.1      cgd     bool bind_now = 0;
    221      1.1      cgd     const char *ld_bind_now;
    222      1.1      cgd     const char **argv;
    223      1.1      cgd 
    224      1.1      cgd     /*
    225      1.1      cgd      * On entry, the dynamic linker itself has not been relocated yet.
    226      1.1      cgd      * Be very careful not to reference any global data until after
    227      1.1      cgd      * _rtld_init has returned.  It is OK to reference file-scope statics
    228      1.1      cgd      * and string constants, and to call static and global functions.
    229      1.1      cgd      */
    230      1.1      cgd     /* Find the auxiliary vector on the stack. */
    231      1.1      cgd     /* first Elf_Word reserved to address of exit routine */
    232      1.1      cgd #ifdef RTLD_DEBUG
    233      1.1      cgd     xprintf("sp = %p, argc = %d, argv = %p <%s>\n", sp, sp[2], &sp[3], sp[3]);
    234      1.1      cgd     xprintf("got is at %p, dynamic is at %p\n", _GLOBAL_OFFSET_TABLE_, &_DYNAMIC);
    235      1.1      cgd     debug = 1;
    236      1.1      cgd     xprintf("_ctype_ is %p\n", _ctype_);
    237      1.1      cgd #endif
    238      1.1      cgd 
    239      1.1      cgd     sp += 2;		/* skip over return argument space */
    240      1.1      cgd     argv = (const char **) &sp[1];
    241      1.1      cgd     sp += sp[0] + 2;	/* Skip over argc, arguments, and NULL terminator */
    242      1.1      cgd     env = (char **) sp;
    243      1.1      cgd     while (*sp++ != 0) {	/* Skip over environment, and NULL terminator */
    244      1.1      cgd #ifdef RTLD_DEBUG
    245      1.1      cgd 	xprintf("env[%d] = %p\n", i++, sp[-1]);
    246      1.1      cgd #endif
    247      1.1      cgd     }
    248      1.1      cgd     aux = (const AuxInfo *) sp;
    249      1.1      cgd 
    250      1.1      cgd     /* Digest the auxiliary vector. */
    251      1.1      cgd     for (i = 0;  i < AUX_count;  ++i)
    252      1.1      cgd 	aux_info[i] = NULL;
    253      1.1      cgd     for (auxp = aux;  auxp->au_id != AUX_null;  ++auxp) {
    254      1.1      cgd 	if (auxp->au_id < AUX_count)
    255      1.1      cgd 	    aux_info[auxp->au_id] = auxp;
    256      1.1      cgd     }
    257      1.1      cgd 
    258      1.1      cgd     /* Initialize and relocate ourselves. */
    259      1.1      cgd     assert(aux_info[AUX_base] != NULL);
    260      1.1      cgd     _rtld_init((caddr_t) aux_info[AUX_base]->au_v);
    261      1.1      cgd 
    262  1.5.2.1  mycroft #ifdef RTLD_DEBUG
    263      1.1      cgd     xprintf("_ctype_ is %p\n", _ctype_);
    264      1.1      cgd #endif
    265  1.5.2.1  mycroft #ifdef DEBUG
    266      1.1      cgd     if (aux_info[AUX_debug] != NULL)	/* Set debugging level */
    267      1.1      cgd 	debug = aux_info[AUX_debug]->au_v;
    268      1.1      cgd #endif
    269      1.1      cgd 
    270      1.1      cgd     __progname = _rtld_objself.path;
    271      1.1      cgd     environ = env;
    272      1.1      cgd 
    273      1.1      cgd     _rtld_trust = geteuid() == getuid() && getegid() == getgid();
    274      1.1      cgd 
    275      1.1      cgd     ld_bind_now = getenv("LD_BIND_NOW");
    276  1.5.2.1  mycroft     if (ld_bind_now != NULL && *ld_bind_now != '\0')
    277      1.1      cgd 	bind_now = true;
    278      1.1      cgd     if (_rtld_trust) {
    279      1.1      cgd #ifdef DEBUG
    280  1.5.2.1  mycroft 	const char *ld_debug = getenv("LD_DEBUG");
    281      1.1      cgd 	if (ld_debug != NULL && *ld_debug != '\0')
    282      1.1      cgd 	    debug = 1;
    283      1.1      cgd #endif
    284      1.1      cgd 	_rtld_add_paths(&_rtld_paths, getenv("LD_LIBRARY_PATH"));
    285      1.1      cgd     }
    286      1.1      cgd 
    287      1.1      cgd     dbg("%s is initialized, base address = %p", __progname,
    288      1.1      cgd 	(caddr_t) aux_info[AUX_base]->au_v);
    289      1.1      cgd 
    290      1.1      cgd     /*
    291      1.1      cgd      * Load the main program, or process its program header if it is
    292      1.1      cgd      * already loaded.
    293      1.1      cgd      */
    294      1.1      cgd     if (aux_info[AUX_execfd] != NULL) {	/* Load the main program. */
    295      1.1      cgd 	int fd = aux_info[AUX_execfd]->au_v;
    296      1.1      cgd 	dbg("loading main program");
    297      1.1      cgd 	_rtld_objmain = _rtld_map_object(argv[0], fd);
    298      1.1      cgd 	close(fd);
    299      1.1      cgd 	if (_rtld_objmain == NULL)
    300      1.1      cgd 	    _rtld_die();
    301      1.1      cgd     } else {				/* Main program already loaded. */
    302      1.1      cgd 	const Elf_Phdr *phdr;
    303      1.1      cgd 	int phnum;
    304      1.1      cgd 	caddr_t entry;
    305      1.1      cgd 
    306      1.1      cgd 	dbg("processing main program's program header");
    307      1.1      cgd 	assert(aux_info[AUX_phdr] != NULL);
    308      1.1      cgd 	phdr = (const Elf_Phdr *) aux_info[AUX_phdr]->au_v;
    309      1.1      cgd 	assert(aux_info[AUX_phnum] != NULL);
    310      1.1      cgd 	phnum = aux_info[AUX_phnum]->au_v;
    311      1.1      cgd 	assert(aux_info[AUX_phent] != NULL);
    312      1.1      cgd 	assert(aux_info[AUX_phent]->au_v == sizeof(Elf_Phdr));
    313      1.1      cgd 	assert(aux_info[AUX_entry] != NULL);
    314      1.1      cgd 	entry = (caddr_t) aux_info[AUX_entry]->au_v;
    315      1.1      cgd 	_rtld_objmain = _rtld_digest_phdr(phdr, phnum, entry);
    316      1.1      cgd     }
    317      1.1      cgd 
    318      1.1      cgd     _rtld_objmain->path = xstrdup("main program");
    319      1.1      cgd     _rtld_objmain->mainprog = true;
    320      1.1      cgd     _rtld_digest_dynamic(_rtld_objmain);
    321      1.1      cgd 
    322      1.1      cgd     _rtld_linkmap_add(_rtld_objmain);
    323      1.1      cgd     _rtld_linkmap_add(&_rtld_objself);
    324      1.1      cgd 
    325      1.1      cgd     /* Link the main program into the list of objects. */
    326      1.1      cgd     *_rtld_objtail = _rtld_objmain;
    327      1.1      cgd     _rtld_objtail = &_rtld_objmain->next;
    328      1.1      cgd     ++_rtld_objmain->refcount;
    329      1.1      cgd 
    330      1.1      cgd     dbg("loading needed objects");
    331      1.1      cgd     if (_rtld_load_needed_objects(_rtld_objmain) == -1)
    332      1.1      cgd 	_rtld_die();
    333      1.1      cgd 
    334      1.1      cgd     dbg("relocating objects");
    335      1.1      cgd     if (_rtld_relocate_objects(_rtld_objmain, bind_now) == -1)
    336      1.1      cgd 	_rtld_die();
    337      1.1      cgd 
    338      1.1      cgd     dbg("doing copy relocations");
    339      1.1      cgd     if (_rtld_do_copy_relocations(_rtld_objmain) == -1)
    340      1.1      cgd 	_rtld_die();
    341      1.1      cgd 
    342      1.1      cgd     dbg("calling _init functions");
    343      1.1      cgd     _rtld_call_init_functions(_rtld_objmain->next);
    344      1.1      cgd 
    345      1.1      cgd     dbg("transferring control to program entry point = %p",
    346      1.1      cgd 	_rtld_objmain->entry);
    347      1.1      cgd 
    348      1.1      cgd     /* Return with the entry point and the exit procedure in at the top of
    349      1.1      cgd      * stack.
    350      1.1      cgd      */
    351      1.1      cgd 
    352      1.1      cgd     _rtld_debug_state();	/* say hello to gdb! */
    353      1.1      cgd 
    354      1.1      cgd     ((void **) osp)[0] = _rtld_exit;
    355      1.1      cgd     ((void **) osp)[1] = _rtld_objmain;
    356      1.1      cgd     return (Elf_Addr) _rtld_objmain->entry;
    357      1.1      cgd }
    358      1.1      cgd 
    359      1.1      cgd void
    360      1.1      cgd _rtld_die(
    361      1.1      cgd     void)
    362      1.1      cgd {
    363      1.1      cgd     const char *msg = _rtld_dlerror();
    364      1.1      cgd 
    365      1.1      cgd     if (msg == NULL)
    366      1.1      cgd 	msg = "Fatal error";
    367      1.1      cgd     xerrx(1, "%s\n", msg);
    368      1.1      cgd }
    369      1.1      cgd 
    370      1.1      cgd static Obj_Entry *
    371      1.1      cgd _rtld_dlcheck(
    372      1.1      cgd     void *handle)
    373      1.1      cgd {
    374      1.1      cgd     Obj_Entry *obj;
    375      1.1      cgd 
    376      1.1      cgd     for (obj = _rtld_objlist;  obj != NULL;  obj = obj->next)
    377      1.1      cgd 	if (obj == (Obj_Entry *) handle)
    378      1.1      cgd 	    break;
    379      1.1      cgd 
    380      1.1      cgd     if (obj == NULL || obj->dl_refcount == 0) {
    381      1.1      cgd 	xwarnx("Invalid shared object handle %p", handle);
    382      1.1      cgd 	return NULL;
    383      1.1      cgd     }
    384      1.1      cgd     return obj;
    385      1.1      cgd }
    386      1.1      cgd 
    387      1.1      cgd static void
    388      1.1      cgd _rtld_unref_object_dag(
    389      1.1      cgd     Obj_Entry *root)
    390      1.1      cgd {
    391      1.1      cgd     assert(root->refcount != 0);
    392      1.1      cgd     --root->refcount;
    393      1.1      cgd     if (root->refcount == 0) {
    394      1.1      cgd 	const Needed_Entry *needed;
    395      1.1      cgd 
    396      1.1      cgd 	for (needed = root->needed;  needed != NULL;  needed = needed->next)
    397      1.1      cgd 	    _rtld_unref_object_dag(needed->obj);
    398      1.1      cgd     }
    399      1.1      cgd }
    400      1.1      cgd 
    401      1.1      cgd int
    402      1.1      cgd _rtld_dlclose(
    403      1.1      cgd     void *handle)
    404      1.1      cgd {
    405      1.1      cgd     Obj_Entry *root = _rtld_dlcheck(handle);
    406      1.1      cgd 
    407      1.1      cgd     if (root == NULL)
    408      1.1      cgd 	return -1;
    409      1.1      cgd 
    410      1.1      cgd     _rtld_debug.r_state = RT_DELETE;
    411      1.1      cgd     _rtld_debug_state();
    412      1.1      cgd 
    413      1.1      cgd     --root->dl_refcount;
    414      1.1      cgd     _rtld_unref_object_dag(root);
    415      1.1      cgd     if (root->refcount == 0) {	/* We are finished with some objects. */
    416      1.1      cgd 	Obj_Entry *obj;
    417      1.1      cgd 	Obj_Entry **linkp;
    418      1.1      cgd 
    419      1.1      cgd 	/* Finalize objects that are about to be unmapped. */
    420      1.1      cgd 	for (obj = _rtld_objlist->next;  obj != NULL;  obj = obj->next)
    421      1.1      cgd 	    if (obj->refcount == 0 && obj->fini != NULL)
    422      1.1      cgd 		(*obj->fini)();
    423      1.1      cgd 
    424      1.1      cgd 	/* Unmap all objects that are no longer referenced. */
    425      1.1      cgd 	linkp = &_rtld_objlist->next;
    426      1.1      cgd 	while((obj = *linkp) != NULL) {
    427      1.1      cgd 	    if (obj->refcount == 0) {
    428      1.1      cgd 		munmap(obj->mapbase, obj->mapsize);
    429      1.1      cgd 		free(obj->path);
    430      1.1      cgd 		while(obj->needed != NULL) {
    431      1.1      cgd 		    Needed_Entry *needed = obj->needed;
    432      1.1      cgd 		    obj->needed = needed->next;
    433      1.1      cgd 		    free(needed);
    434      1.1      cgd 		}
    435      1.1      cgd 		_rtld_linkmap_delete(obj);
    436      1.1      cgd 		*linkp = obj->next;
    437      1.1      cgd 		free(obj);
    438      1.1      cgd 	    } else
    439      1.1      cgd 		linkp = &obj->next;
    440      1.1      cgd 	}
    441      1.1      cgd     }
    442      1.1      cgd 
    443      1.1      cgd     _rtld_debug.r_state = RT_CONSISTENT;
    444      1.1      cgd     _rtld_debug_state();
    445      1.1      cgd 
    446      1.1      cgd     return 0;
    447      1.1      cgd }
    448      1.1      cgd 
    449      1.1      cgd char *
    450      1.1      cgd _rtld_dlerror(
    451      1.1      cgd     void)
    452      1.1      cgd {
    453      1.1      cgd     char *msg = error_message;
    454      1.1      cgd     error_message = NULL;
    455      1.1      cgd     return msg;
    456      1.1      cgd }
    457      1.1      cgd 
    458      1.1      cgd void *
    459      1.1      cgd _rtld_dlopen(
    460      1.1      cgd     const char *name,
    461      1.1      cgd     int mode)
    462      1.1      cgd {
    463      1.1      cgd     Obj_Entry **old_obj_tail = _rtld_objtail;
    464      1.1      cgd     Obj_Entry *obj = NULL;
    465      1.1      cgd 
    466      1.1      cgd     _rtld_debug.r_state = RT_ADD;
    467      1.1      cgd     _rtld_debug_state();
    468      1.1      cgd 
    469      1.1      cgd     if (name == NULL) {
    470      1.1      cgd 	obj = _rtld_objmain;
    471      1.1      cgd     } else {
    472      1.1      cgd 	char *path = _rtld_find_library(name, NULL);
    473      1.1      cgd 	if (path != NULL)
    474      1.1      cgd 	    obj = _rtld_load_object(path);
    475      1.1      cgd     }
    476      1.1      cgd 
    477      1.1      cgd     if (obj != NULL) {
    478      1.1      cgd 	++obj->dl_refcount;
    479      1.1      cgd 	if (*old_obj_tail != NULL) {		/* We loaded something new. */
    480      1.1      cgd 	    assert(*old_obj_tail == obj);
    481      1.1      cgd 
    482      1.1      cgd 	    /* FIXME - Clean up properly after an error. */
    483      1.1      cgd 	    if (_rtld_load_needed_objects(obj) == -1) {
    484      1.1      cgd 		--obj->dl_refcount;
    485      1.1      cgd 		obj = NULL;
    486      1.1      cgd 	    } else if (_rtld_relocate_objects(obj, mode == RTLD_NOW) == -1) {
    487      1.1      cgd 		--obj->dl_refcount;
    488      1.1      cgd 		obj = NULL;
    489      1.1      cgd 	    } else {
    490      1.1      cgd 		_rtld_call_init_functions(obj);
    491      1.1      cgd 	    }
    492      1.1      cgd 	}
    493      1.1      cgd     }
    494      1.1      cgd 
    495      1.1      cgd     _rtld_debug.r_state = RT_CONSISTENT;
    496      1.1      cgd     _rtld_debug_state();
    497      1.1      cgd 
    498      1.1      cgd     return obj;
    499      1.1      cgd }
    500      1.1      cgd 
    501      1.1      cgd void *
    502      1.1      cgd _rtld_dlsym(
    503      1.1      cgd     void *handle,
    504      1.1      cgd     const char *name)
    505      1.1      cgd {
    506      1.1      cgd     const Obj_Entry *obj = _rtld_dlcheck(handle);
    507      1.1      cgd     const Elf_Sym *def;
    508      1.1      cgd     const Obj_Entry *defobj;
    509      1.1      cgd 
    510      1.1      cgd     if (obj == NULL)
    511      1.1      cgd 	return NULL;
    512      1.1      cgd 
    513      1.1      cgd     /*
    514      1.1      cgd      * FIXME - This isn't correct.  The search should include the whole
    515      1.1      cgd      * DAG rooted at the given object.
    516      1.1      cgd      */
    517      1.1      cgd     def = _rtld_find_symdef(_rtld_objlist, 0, name, obj, &defobj, false);
    518      1.1      cgd     if (def != NULL)
    519      1.1      cgd 	return defobj->relocbase + def->st_value;
    520      1.1      cgd 
    521      1.1      cgd     _rtld_error("Undefined symbol \"%s\"", name);
    522      1.1      cgd     return NULL;
    523      1.1      cgd }
    524      1.1      cgd 
    525      1.1      cgd /*
    526      1.1      cgd  * Error reporting function.  Use it like printf.  If formats the message
    527      1.1      cgd  * into a buffer, and sets things up so that the next call to dlerror()
    528      1.1      cgd  * will return the message.
    529      1.1      cgd  */
    530      1.1      cgd void
    531      1.1      cgd _rtld_error(
    532      1.1      cgd     const char *fmt, ...)
    533      1.1      cgd {
    534      1.1      cgd     static char buf[512];
    535      1.1      cgd     va_list ap;
    536      1.1      cgd 
    537      1.1      cgd     va_start(ap, fmt);
    538      1.1      cgd     xvsnprintf(buf, sizeof buf, fmt, ap);
    539      1.1      cgd     error_message = buf;
    540      1.1      cgd     va_end(ap);
    541      1.1      cgd }
    542      1.1      cgd 
    543      1.1      cgd void
    545      1.1      cgd _rtld_debug_state(
    546      1.1      cgd     void)
    547      1.1      cgd {
    548      1.1      cgd     /* do nothing */
    549      1.1      cgd }
    550      1.1      cgd 
    551      1.1      cgd void
    552      1.1      cgd _rtld_linkmap_add(
    553      1.1      cgd     Obj_Entry *obj)
    554      1.1      cgd {
    555      1.1      cgd     struct link_map *l = &obj->linkmap;
    556      1.1      cgd     struct link_map *prev;
    557  1.5.2.1  mycroft 
    558  1.5.2.1  mycroft     obj->linkmap.l_name = obj->path;
    559  1.5.2.1  mycroft     obj->linkmap.l_addr = obj->mapbase;
    560  1.5.2.1  mycroft     obj->linkmap.l_ld = obj->dynamic;
    561      1.1      cgd #ifdef __mips__
    562      1.1      cgd     /* GDB needs load offset on MIPS to use the symbols */
    563      1.1      cgd     obj->linkmap.l_offs = obj->relocbase;
    564      1.1      cgd #endif
    565      1.1      cgd 
    566      1.1      cgd     if (_rtld_debug.r_map == NULL) {
    567      1.1      cgd 	_rtld_debug.r_map = l;
    568      1.1      cgd 	return;
    569      1.1      cgd     }
    570      1.1      cgd 
    571      1.1      cgd     for (prev = _rtld_debug.r_map; prev->l_next != NULL; prev = prev->l_next)
    572      1.1      cgd 	;
    573      1.1      cgd     l->l_prev = prev;
    574      1.1      cgd     prev->l_next = l;
    575      1.1      cgd     l->l_next = NULL;
    576      1.1      cgd }
    577      1.1      cgd 
    578      1.1      cgd void
    579      1.1      cgd _rtld_linkmap_delete(
    580      1.1      cgd     Obj_Entry *obj)
    581      1.1      cgd {
    582      1.1      cgd     struct link_map *l = &obj->linkmap;
    583      1.1      cgd 
    584      1.1      cgd     if (l->l_prev == NULL) {
    585      1.1      cgd 	if ((_rtld_debug.r_map = l->l_next) != NULL)
    586      1.1      cgd 	    l->l_next->l_prev = NULL;
    587      1.1      cgd 	return;
    588      1.1      cgd     }
    589                   
    590                       if ((l->l_prev->l_next = l->l_next) != NULL)
    591                   	l->l_next->l_prev = l->l_prev;
    592                   }
    593