rtld.c revision 70677
118334Speter/*-
290075Sobrien * Copyright 1996, 1997, 1998, 1999, 2000 John D. Polstra.
3169689Skan * All rights reserved.
4169689Skan *
518334Speter * Redistribution and use in source and binary forms, with or without
690075Sobrien * modification, are permitted provided that the following conditions
718334Speter * are met:
890075Sobrien * 1. Redistributions of source code must retain the above copyright
990075Sobrien *    notice, this list of conditions and the following disclaimer.
1090075Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1190075Sobrien *    notice, this list of conditions and the following disclaimer in the
1218334Speter *    documentation and/or other materials provided with the distribution.
1390075Sobrien *
1490075Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1590075Sobrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1690075Sobrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1718334Speter * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1818334Speter * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1990075Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20169689Skan * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21169689Skan * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2218334Speter * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2318334Speter * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2418334Speter *
2550397Sobrien * $FreeBSD: head/libexec/rtld-elf/rtld.c 70677 2001-01-05 04:36:17Z jdp $
26132718Skan */
27132718Skan
2818334Speter/*
2950397Sobrien * Dynamic linker for ELF.
3090075Sobrien *
3118334Speter * John Polstra <jdp@polstra.com>.
3218334Speter */
3350397Sobrien
34169689Skan#ifndef __GNUC__
3550397Sobrien#error "GCC is needed to compile this file"
3690075Sobrien#endif
3796263Sobrien
38117395Skan#include <sys/param.h>
39169689Skan#include <sys/mman.h>
40169689Skan#include <sys/stat.h>
4118334Speter
4218334Speter#include <dlfcn.h>
4350397Sobrien#include <err.h>
4490075Sobrien#include <errno.h>
4518334Speter#include <fcntl.h>
4618334Speter#include <stdarg.h>
4718334Speter#include <stdio.h>
48169689Skan#include <stdlib.h>
49169689Skan#include <string.h>
50169689Skan#include <unistd.h>
5118334Speter
5290075Sobrien#include "debug.h"
5390075Sobrien#include "rtld.h"
5490075Sobrien
5590075Sobrien#define END_SYM		"_end"
5690075Sobrien#define PATH_RTLD	"/usr/libexec/ld-elf.so.1"
57132718Skan
58132718Skan/* Types. */
59132718Skantypedef void (*func_ptr_type)();
60132718Skan
61132718Skan/*
62132718Skan * This structure provides a reentrant way to keep a list of objects and
63132718Skan * check which ones have already been processed in some way.
64132718Skan */
6518334Spetertypedef struct Struct_DoneList {
6618334Speter    const Obj_Entry **objs;		/* Array of object pointers */
6718334Speter    unsigned int num_alloc;		/* Allocated size of the array */
68117395Skan    unsigned int num_used;		/* Number of array slots used */
6918334Speter} DoneList;
7090075Sobrien
7190075Sobrien/*
7290075Sobrien * Function declarations.
7390075Sobrien */
74132718Skanstatic const char *basename(const char *);
7590075Sobrienstatic void die(void);
7690075Sobrienstatic void digest_dynamic(Obj_Entry *);
7790075Sobrienstatic Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *);
7890075Sobrienstatic Obj_Entry *dlcheck(void *);
7990075Sobrienstatic bool donelist_check(DoneList *, const Obj_Entry *);
8090075Sobrienstatic void errmsg_restore(char *);
8118334Speterstatic char *errmsg_save(void);
82132718Skanstatic char *find_library(const char *, const Obj_Entry *);
8318334Speterstatic const char *gethints(void);
8418334Speterstatic void init_dag(Obj_Entry *);
8518334Speterstatic void init_dag1(Obj_Entry *root, Obj_Entry *obj, DoneList *);
8618334Speterstatic void init_rtld(caddr_t);
8718334Speterstatic void initlist_add_neededs(Needed_Entry *needed, Objlist *list);
8818334Speterstatic void initlist_add_objects(Obj_Entry *obj, Obj_Entry **tail,
8918334Speter  Objlist *list);
9090075Sobrienstatic bool is_exported(const Elf_Sym *);
9190075Sobrienstatic void linkmap_add(Obj_Entry *);
9218334Speterstatic void linkmap_delete(Obj_Entry *);
93132718Skanstatic int load_needed_objects(Obj_Entry *);
9490075Sobrienstatic int load_preload_objects(void);
9590075Sobrienstatic Obj_Entry *load_object(char *);
9690075Sobrienstatic void lock_check(void);
97132718Skanstatic Obj_Entry *obj_from_addr(const void *);
9890075Sobrienstatic void objlist_call_fini(Objlist *);
9990075Sobrienstatic void objlist_call_init(Objlist *);
10090075Sobrienstatic void objlist_clear(Objlist *);
10190075Sobrienstatic Objlist_Entry *objlist_find(Objlist *, const Obj_Entry *);
10290075Sobrienstatic void objlist_init(Objlist *);
10390075Sobrienstatic void objlist_push_head(Objlist *, Obj_Entry *);
10490075Sobrienstatic void objlist_push_tail(Objlist *, Obj_Entry *);
10590075Sobrienstatic void objlist_remove(Objlist *, Obj_Entry *);
10690075Sobrienstatic void objlist_remove_unref(Objlist *);
107132718Skanstatic int relocate_objects(Obj_Entry *, bool);
10818334Speterstatic void rtld_exit(void);
109169689Skanstatic char *search_library_path(const char *, const char *);
11018334Speterstatic void set_program_var(const char *, const void *);
11118334Speterstatic const Elf_Sym *symlook_default(const char *, unsigned long hash,
11218334Speter  const Obj_Entry *refobj, const Obj_Entry **defobj_out, bool in_plt);
11318334Speterstatic const Elf_Sym *symlook_list(const char *, unsigned long,
11418334Speter  Objlist *, const Obj_Entry **, bool in_plt, DoneList *);
11518334Speterstatic void trace_loaded_objects(Obj_Entry *obj);
11618334Speterstatic void unload_object(Obj_Entry *);
117132718Skanstatic void unref_dag(Obj_Entry *);
11818334Speter
119132718Skanvoid r_debug_state(struct r_debug*, struct link_map*);
120132718Skanvoid xprintf(const char *, ...);
12118334Speter
12218334Speter/*
12390075Sobrien * Data declarations.
12490075Sobrien */
12518334Speterstatic char *error_message;	/* Message for dlerror(), or NULL */
126169689Skanstruct r_debug r_debug;	/* for GDB; */
127132718Skanstatic bool trust;		/* False for setuid and setgid programs */
12818334Speterstatic char *ld_bind_now;	/* Environment variable for immediate binding */
12918334Speterstatic char *ld_debug;		/* Environment variable for debugging */
130169689Skanstatic char *ld_library_path;	/* Environment variable for search path */
13118334Speterstatic char *ld_preload;	/* Environment variable for libraries to
13290075Sobrien				   load first */
13390075Sobrienstatic char *ld_tracing;	/* Called from ldd to print libs */
13490075Sobrienstatic Obj_Entry *obj_list;	/* Head of linked list of shared objects */
13590075Sobrienstatic Obj_Entry **obj_tail;	/* Link field of last object in list */
13690075Sobrienstatic Obj_Entry *obj_main;	/* The main program shared object */
13790075Sobrienstatic Obj_Entry obj_rtld;	/* The dynamic linker shared object */
13890075Sobrienstatic unsigned int obj_count;	/* Number of objects in obj_list */
13990075Sobrien
140169689Skanstatic Objlist list_global =	/* Objects dlopened with RTLD_GLOBAL */
14190075Sobrien  STAILQ_HEAD_INITIALIZER(list_global);
142169689Skanstatic Objlist list_main =	/* Objects loaded at program startup */
143169689Skan  STAILQ_HEAD_INITIALIZER(list_main);
144169689Skanstatic Objlist list_fini =	/* Objects needing fini() calls */
145169689Skan  STAILQ_HEAD_INITIALIZER(list_fini);
146169689Skan
147169689Skanstatic LockInfo lockinfo;
14818334Speter
14918334Speterstatic Elf_Sym sym_zero;	/* For resolving undefined weak refs. */
150169689Skan
15118334Speter#define GDB_STATE(s,m)	r_debug.r_state = s; r_debug_state(&r_debug,m);
15218334Speter
15318334Speterextern Elf_Dyn _DYNAMIC;
15490075Sobrien#pragma weak _DYNAMIC
15518334Speter
15618334Speter/*
157169689Skan * These are the functions the dynamic linker exports to application
15818334Speter * programs.  They are the only symbols the dynamic linker is willing
15918334Speter * to export from itself.
16018334Speter */
16118334Speterstatic func_ptr_type exports[] = {
16218334Speter    (func_ptr_type) &_rtld_error,
16318334Speter    (func_ptr_type) &dlclose,
16418334Speter    (func_ptr_type) &dlerror,
16518334Speter    (func_ptr_type) &dlopen,
166132718Skan    (func_ptr_type) &dlsym,
167132718Skan    (func_ptr_type) &dladdr,
168132718Skan    (func_ptr_type) &dllockinit,
169132718Skan    NULL
17018334Speter};
17118334Speter
172132718Skan/*
17318334Speter * Global declarations normally provided by crt1.  The dynamic linker is
17490075Sobrien * not built with crt1, so we have to provide them ourselves.
17518334Speter */
17690075Sobrienchar *__progname;
17718334Speterchar **environ;
17818334Speter
17918334Speter/*
18018334Speter * Fill in a DoneList with an allocation large enough to hold all of
18118334Speter * the currently-loaded objects.  Keep this as a macro since it calls
182132718Skan * alloca and we want that to occur within the scope of the caller.
18318334Speter */
18418334Speter#define donelist_init(dlp)					\
18518334Speter    ((dlp)->objs = alloca(obj_count * sizeof (dlp)->objs[0]),	\
18618334Speter    assert((dlp)->objs != NULL),				\
18718334Speter    (dlp)->num_alloc = obj_count,				\
18890075Sobrien    (dlp)->num_used = 0)
18990075Sobrien
19090075Sobrienstatic __inline void
191132718Skanrlock_acquire(void)
19290075Sobrien{
193169689Skan    lockinfo.rlock_acquire(lockinfo.thelock);
194169689Skan    atomic_incr_int(&lockinfo.rcount);
195169689Skan    lock_check();
196169689Skan}
19790075Sobrien
198169689Skanstatic __inline void
199169689Skanwlock_acquire(void)
200169689Skan{
201169689Skan    lockinfo.wlock_acquire(lockinfo.thelock);
202169689Skan    atomic_incr_int(&lockinfo.wcount);
20390075Sobrien    lock_check();
20490075Sobrien}
20518334Speter
206132718Skanstatic __inline void
20718334Speterrlock_release(void)
20852284Sobrien{
209132718Skan    atomic_decr_int(&lockinfo.rcount);
21018334Speter    lockinfo.rlock_release(lockinfo.thelock);
21190075Sobrien}
21218334Speter
21318334Speterstatic __inline void
21418334Speterwlock_release(void)
21518334Speter{
21618334Speter    atomic_decr_int(&lockinfo.wcount);
217132718Skan    lockinfo.wlock_release(lockinfo.thelock);
21818334Speter}
21918334Speter
220169689Skan/*
22118334Speter * Main entry point for dynamic linking.  The first argument is the
22218334Speter * stack pointer.  The stack is expected to be laid out as described
22352284Sobrien * in the SVR4 ABI specification, Intel 386 Processor Supplement.
22452284Sobrien * Specifically, the stack pointer points to a word containing
22552284Sobrien * ARGC.  Following that in the stack is a null-terminated sequence
226132718Skan * of pointers to argument strings.  Then comes a null-terminated
22752284Sobrien * sequence of pointers to environment strings.  Finally, there is a
22852284Sobrien * sequence of "auxiliary vector" entries.
22952284Sobrien *
23052284Sobrien * The second argument points to a place to store the dynamic linker's
23152284Sobrien * exit procedure pointer and the third to a place to store the main
23252284Sobrien * program's object.
23352284Sobrien *
23452284Sobrien * The return value is the main program's entry point.
23552284Sobrien */
23652284Sobrienfunc_ptr_type
237169689Skan_rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
23890075Sobrien{
23990075Sobrien    Elf_Auxinfo *aux_info[AT_COUNT];
24052284Sobrien    int i;
24152284Sobrien    int argc;
24252284Sobrien    char **argv;
24352284Sobrien    char **env;
24452284Sobrien    Elf_Auxinfo *aux;
245117395Skan    Elf_Auxinfo *auxp;
24652284Sobrien    const char *argv0;
24790075Sobrien    Obj_Entry *obj;
24890075Sobrien    Obj_Entry **preload_tail;
24952284Sobrien    Objlist initlist;
25052284Sobrien
251169689Skan    /*
25252284Sobrien     * On entry, the dynamic linker itself has not been relocated yet.
25352284Sobrien     * Be very careful not to reference any global data until after
25452284Sobrien     * init_rtld has returned.  It is OK to reference file-scope statics
25552284Sobrien     * and string constants, and to call static and global functions.
25652284Sobrien     */
257117395Skan
258117395Skan    /* Find the auxiliary vector on the stack. */
259117395Skan    argc = *sp++;
260117395Skan    argv = (char **) sp;
261132718Skan    sp += argc + 1;	/* Skip over arguments and NULL terminator */
262117395Skan    env = (char **) sp;
263132718Skan    while (*sp++ != 0)	/* Skip over environment, and NULL terminator */
264117395Skan	;
265117395Skan    aux = (Elf_Auxinfo *) sp;
26618334Speter
267132718Skan    /* Digest the auxiliary vector. */
268132718Skan    for (i = 0;  i < AT_COUNT;  i++)
269132718Skan	aux_info[i] = NULL;
270132718Skan    for (auxp = aux;  auxp->a_type != AT_NULL;  auxp++) {
271132718Skan	if (auxp->a_type < AT_COUNT)
272132718Skan	    aux_info[auxp->a_type] = auxp;
273132718Skan    }
274132718Skan
275132718Skan    /* Initialize and relocate ourselves. */
276132718Skan    assert(aux_info[AT_BASE] != NULL);
277132718Skan    init_rtld((caddr_t) aux_info[AT_BASE]->a_un.a_ptr);
278132718Skan
279132718Skan    __progname = obj_rtld.path;
280132718Skan    argv0 = argv[0] != NULL ? argv[0] : "(null)";
28118334Speter    environ = env;
28218334Speter
28318334Speter    trust = geteuid() == getuid() && getegid() == getgid();
28418334Speter
28518334Speter    ld_bind_now = getenv("LD_BIND_NOW");
28618334Speter    if (trust) {
28718334Speter	ld_debug = getenv("LD_DEBUG");
28818334Speter	ld_library_path = getenv("LD_LIBRARY_PATH");
28918334Speter	ld_preload = getenv("LD_PRELOAD");
29018334Speter    }
29118334Speter    ld_tracing = getenv("LD_TRACE_LOADED_OBJECTS");
29218334Speter
29318334Speter    if (ld_debug != NULL && *ld_debug != '\0')
29418334Speter	debug = 1;
295132718Skan    dbg("%s is initialized, base address = %p", __progname,
29618334Speter	(caddr_t) aux_info[AT_BASE]->a_un.a_ptr);
29790075Sobrien    dbg("RTLD dynamic = %p", obj_rtld.dynamic);
29890075Sobrien    dbg("RTLD pltgot  = %p", obj_rtld.pltgot);
299117395Skan
30018334Speter    /*
30118334Speter     * Load the main program, or process its program header if it is
30218334Speter     * already loaded.
30318334Speter     */
304169689Skan    if (aux_info[AT_EXECFD] != NULL) {	/* Load the main program. */
305169689Skan	int fd = aux_info[AT_EXECFD]->a_un.a_val;
306169689Skan	dbg("loading main program");
307117395Skan	obj_main = map_object(fd, argv0, NULL);
308117395Skan	close(fd);
30918334Speter	if (obj_main == NULL)
31090075Sobrien	    die();
31118334Speter    } else {				/* Main program already loaded. */
31290075Sobrien	const Elf_Phdr *phdr;
31390075Sobrien	int phnum;
31490075Sobrien	caddr_t entry;
31590075Sobrien
31690075Sobrien	dbg("processing main program's program header");
31790075Sobrien	assert(aux_info[AT_PHDR] != NULL);
31890075Sobrien	phdr = (const Elf_Phdr *) aux_info[AT_PHDR]->a_un.a_ptr;
31990075Sobrien	assert(aux_info[AT_PHNUM] != NULL);
32090075Sobrien	phnum = aux_info[AT_PHNUM]->a_un.a_val;
32118334Speter	assert(aux_info[AT_PHENT] != NULL);
322169689Skan	assert(aux_info[AT_PHENT]->a_un.a_val == sizeof(Elf_Phdr));
32390075Sobrien	assert(aux_info[AT_ENTRY] != NULL);
32490075Sobrien	entry = (caddr_t) aux_info[AT_ENTRY]->a_un.a_ptr;
32590075Sobrien	if ((obj_main = digest_phdr(phdr, phnum, entry, argv0)) == NULL)
32618334Speter	    die();
32718334Speter    }
32890075Sobrien
32990075Sobrien    obj_main->path = xstrdup(argv0);
33090075Sobrien    obj_main->mainprog = true;
331132718Skan
33290075Sobrien    /*
333169689Skan     * Get the actual dynamic linker pathname from the executable if
334169689Skan     * possible.  (It should always be possible.)  That ensures that
33518334Speter     * gdb will find the right dynamic linker even if a non-standard
336132718Skan     * one is being used.
337132718Skan     */
338132718Skan    if (obj_main->interp != NULL &&
339132718Skan      strcmp(obj_main->interp, obj_rtld.path) != 0) {
340132718Skan	free(obj_rtld.path);
341117395Skan	obj_rtld.path = xstrdup(obj_main->interp);
342132718Skan    }
343169689Skan
344169689Skan    digest_dynamic(obj_main);
345169689Skan
34618334Speter    linkmap_add(obj_main);
347132718Skan    linkmap_add(&obj_rtld);
348132718Skan
349132718Skan    /* Link the main program into the list of objects. */
35090075Sobrien    *obj_tail = obj_main;
351132718Skan    obj_tail = &obj_main->next;
352169689Skan    obj_count++;
353169689Skan    obj_main->refcount++;
354132718Skan    /* Make sure we don't call the main program's init and fini functions. */
355169689Skan    obj_main->init = obj_main->fini = NULL;
356132718Skan
357169689Skan    /* Initialize a fake symbol for resolving undefined weak references. */
358169689Skan    sym_zero.st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE);
359132718Skan    sym_zero.st_shndx = SHN_ABS;
360132718Skan
361132718Skan    dbg("loading LD_PRELOAD libraries");
362132718Skan    if (load_preload_objects() == -1)
363132718Skan	die();
364132718Skan    preload_tail = obj_tail;
365132718Skan
366132718Skan    dbg("loading needed objects");
367132718Skan    if (load_needed_objects(obj_main) == -1)
368132718Skan	die();
369132718Skan
370132718Skan    /* Make a list of all objects loaded at startup. */
371132718Skan    for (obj = obj_list;  obj != NULL;  obj = obj->next)
372132718Skan	objlist_push_tail(&list_main, obj);
373132718Skan
374132718Skan    if (ld_tracing) {		/* We're done */
375132718Skan	trace_loaded_objects(obj_main);
376132718Skan	exit(0);
377132718Skan    }
378132718Skan
379132718Skan    if (relocate_objects(obj_main,
380132718Skan	ld_bind_now != NULL && *ld_bind_now != '\0') == -1)
381132718Skan	die();
382132718Skan
383132718Skan    dbg("doing copy relocations");
384132718Skan    if (do_copy_relocations(obj_main) == -1)
385169689Skan	die();
386132718Skan
387132718Skan    dbg("initializing key program variables");
388132718Skan    set_program_var("__progname", argv[0] != NULL ? basename(argv[0]) : "");
389132718Skan    set_program_var("environ", env);
390132718Skan
391132718Skan    dbg("initializing thread locks");
392132718Skan    lockdflt_init(&lockinfo);
393132718Skan    lockinfo.thelock = lockinfo.lock_create(lockinfo.context);
394132718Skan
395132718Skan    /* Make a list of init functions to call. */
396132718Skan    objlist_init(&initlist);
397132718Skan    initlist_add_objects(obj_list, preload_tail, &initlist);
398132718Skan
399132718Skan    r_debug_state(NULL, &obj_main->linkmap); /* say hello to gdb! */
400132718Skan
401132718Skan    objlist_call_init(&initlist);
402169689Skan    wlock_acquire();
403132718Skan    objlist_clear(&initlist);
404132718Skan    wlock_release();
405132718Skan
406132718Skan    dbg("transferring control to program entry point = %p", obj_main->entry);
407132718Skan
408132718Skan    /* Return the exit procedure and the program entry point. */
409132718Skan    *exit_proc = rtld_exit;
41090075Sobrien    *objp = obj_main;
41190075Sobrien    return (func_ptr_type) obj_main->entry;
41290075Sobrien}
413132718Skan
41418334SpeterElf_Addr
415132718Skan_rtld_bind(Obj_Entry *obj, Elf_Word reloff)
416132718Skan{
417169689Skan    const Elf_Rel *rel;
418132718Skan    const Elf_Sym *def;
419132718Skan    const Obj_Entry *defobj;
420132718Skan    Elf_Addr *where;
421132718Skan    Elf_Addr target;
422132718Skan
42318334Speter    rlock_acquire();
424169689Skan    if (obj->pltrel)
42518334Speter	rel = (const Elf_Rel *) ((caddr_t) obj->pltrel + reloff);
426132718Skan    else
427132718Skan	rel = (const Elf_Rel *) ((caddr_t) obj->pltrela + reloff);
428132718Skan
429132718Skan    where = (Elf_Addr *) (obj->relocbase + rel->r_offset);
430132718Skan    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true);
431132718Skan    if (def == NULL)
432132718Skan	die();
433132718Skan
434132718Skan    target = (Elf_Addr)(defobj->relocbase + def->st_value);
435132718Skan
43618334Speter    dbg("\"%s\" in \"%s\" ==> %p in \"%s\"",
437169689Skan      defobj->strtab + def->st_name, basename(obj->path),
438169689Skan      (void *)target, basename(defobj->path));
439169689Skan
440169689Skan    reloc_jmpslot(where, target);
441169689Skan    rlock_release();
442169689Skan    return target;
443169689Skan}
444169689Skan
44518334Speter/*
44618334Speter * Error reporting function.  Use it like printf.  If formats the message
44718334Speter * into a buffer, and sets things up so that the next call to dlerror()
44818334Speter * will return the message.
44918334Speter */
45090075Sobrienvoid
45190075Sobrien_rtld_error(const char *fmt, ...)
45290075Sobrien{
45390075Sobrien    static char buf[512];
45490075Sobrien    va_list ap;
45590075Sobrien
45690075Sobrien    va_start(ap, fmt);
45790075Sobrien    vsnprintf(buf, sizeof buf, fmt, ap);
45890075Sobrien    error_message = buf;
45990075Sobrien    va_end(ap);
46090075Sobrien}
46190075Sobrien
46290075Sobrien/*
46390075Sobrien * Return a dynamically-allocated copy of the current error message, if any.
464132718Skan */
46590075Sobrienstatic char *
46690075Sobrienerrmsg_save(void)
467169689Skan{
46890075Sobrien    return error_message == NULL ? NULL : xstrdup(error_message);
469169689Skan}
470169689Skan
47190075Sobrien/*
47290075Sobrien * Restore the current error message from a copy which was previously saved
473117395Skan * by errmsg_save().  The copy is freed.
474117395Skan */
475117395Skanstatic void
476117395Skanerrmsg_restore(char *saved_msg)
477117395Skan{
478117395Skan    if (saved_msg == NULL)
479117395Skan	error_message = NULL;
480117395Skan    else {
481117395Skan	_rtld_error("%s", saved_msg);
48218334Speter	free(saved_msg);
483169689Skan    }
484169689Skan}
485169689Skan
486169689Skanstatic const char *
487169689Skanbasename(const char *name)
488169689Skan{
489169689Skan    const char *p = strrchr(name, '/');
490169689Skan    return p != NULL ? p + 1 : name;
491169689Skan}
492169689Skan
493169689Skanstatic void
494169689Skandie(void)
495169689Skan{
496169689Skan    const char *msg = dlerror();
497169689Skan
49818334Speter    if (msg == NULL)
49990075Sobrien	msg = "Fatal error";
50090075Sobrien    errx(1, "%s", msg);
50118334Speter}
502169689Skan
50318334Speter/*
50490075Sobrien * Process a shared object's DYNAMIC section, and save the important
505132718Skan * information in its Obj_Entry structure.
50690075Sobrien */
50790075Sobrienstatic void
50890075Sobriendigest_dynamic(Obj_Entry *obj)
50918334Speter{
51090075Sobrien    const Elf_Dyn *dynp;
51190075Sobrien    Needed_Entry **needed_tail = &obj->needed;
51290075Sobrien    const Elf_Dyn *dyn_rpath = NULL;
513117395Skan    int plttype = DT_REL;
51490075Sobrien
51590075Sobrien    for (dynp = obj->dynamic;  dynp->d_tag != DT_NULL;  dynp++) {
51690075Sobrien	switch (dynp->d_tag) {
51790075Sobrien
518132718Skan	case DT_REL:
51918334Speter	    obj->rel = (const Elf_Rel *) (obj->relocbase + dynp->d_un.d_ptr);
520132718Skan	    break;
52118334Speter
52290075Sobrien	case DT_RELSZ:
52390075Sobrien	    obj->relsize = dynp->d_un.d_val;
52490075Sobrien	    break;
52590075Sobrien
52690075Sobrien	case DT_RELENT:
52790075Sobrien	    assert(dynp->d_un.d_val == sizeof(Elf_Rel));
528132718Skan	    break;
52990075Sobrien
53090075Sobrien	case DT_JMPREL:
53150397Sobrien	    obj->pltrel = (const Elf_Rel *)
53250397Sobrien	      (obj->relocbase + dynp->d_un.d_ptr);
53390075Sobrien	    break;
534132718Skan
53550397Sobrien	case DT_PLTRELSZ:
53618334Speter	    obj->pltrelsize = dynp->d_un.d_val;
53790075Sobrien	    break;
53890075Sobrien
53996263Sobrien	case DT_RELA:
54090075Sobrien	    obj->rela = (const Elf_Rela *) (obj->relocbase + dynp->d_un.d_ptr);
54190075Sobrien	    break;
542169689Skan
54390075Sobrien	case DT_RELASZ:
54490075Sobrien	    obj->relasize = dynp->d_un.d_val;
54590075Sobrien	    break;
54690075Sobrien
54790075Sobrien	case DT_RELAENT:
54890075Sobrien	    assert(dynp->d_un.d_val == sizeof(Elf_Rela));
54990075Sobrien	    break;
55090075Sobrien
551132718Skan	case DT_PLTREL:
55290075Sobrien	    plttype = dynp->d_un.d_val;
55390075Sobrien	    assert(dynp->d_un.d_val == DT_REL || plttype == DT_RELA);
554169689Skan	    break;
555169689Skan
55690075Sobrien	case DT_SYMTAB:
55790075Sobrien	    obj->symtab = (const Elf_Sym *)
55890075Sobrien	      (obj->relocbase + dynp->d_un.d_ptr);
55990075Sobrien	    break;
560132718Skan
56190075Sobrien	case DT_SYMENT:
56290075Sobrien	    assert(dynp->d_un.d_val == sizeof(Elf_Sym));
563169689Skan	    break;
564169689Skan
565169689Skan	case DT_STRTAB:
56690075Sobrien	    obj->strtab = (const char *) (obj->relocbase + dynp->d_un.d_ptr);
56790075Sobrien	    break;
56890075Sobrien
569132718Skan	case DT_STRSZ:
570132718Skan	    obj->strsize = dynp->d_un.d_val;
57190075Sobrien	    break;
57290075Sobrien
573169689Skan	case DT_HASH:
574169689Skan	    {
575169689Skan		const Elf_Addr *hashtab = (const Elf_Addr *)
57690075Sobrien		  (obj->relocbase + dynp->d_un.d_ptr);
57790075Sobrien		obj->nbuckets = hashtab[0];
57890075Sobrien		obj->nchains = hashtab[1];
57990075Sobrien		obj->buckets = hashtab + 2;
58090075Sobrien		obj->chains = obj->buckets + obj->nbuckets;
58190075Sobrien	    }
58290075Sobrien	    break;
58390075Sobrien
584132718Skan	case DT_NEEDED:
58590075Sobrien	    if (!obj->rtld) {
58690075Sobrien		Needed_Entry *nep = NEW(Needed_Entry);
58790075Sobrien		nep->name = dynp->d_un.d_val;
58890075Sobrien		nep->obj = NULL;
58918334Speter		nep->next = NULL;
59090075Sobrien
59190075Sobrien		*needed_tail = nep;
59218334Speter		needed_tail = &nep->next;
59390075Sobrien	    }
59490075Sobrien	    break;
595169689Skan
596169689Skan	case DT_PLTGOT:
59790075Sobrien	    obj->pltgot = (Elf_Addr *) (obj->relocbase + dynp->d_un.d_ptr);
598117395Skan	    break;
59990075Sobrien
60090075Sobrien	case DT_TEXTREL:
60190075Sobrien	    obj->textrel = true;
60290075Sobrien	    break;
60318334Speter
60490075Sobrien	case DT_SYMBOLIC:
60518334Speter	    obj->symbolic = true;
60690075Sobrien	    break;
607132718Skan
60890075Sobrien	case DT_RPATH:
60990075Sobrien	    /*
61090075Sobrien	     * We have to wait until later to process this, because we
61190075Sobrien	     * might not have gotten the address of the string table yet.
61290075Sobrien	     */
613132718Skan	    dyn_rpath = dynp;
614132718Skan	    break;
61590075Sobrien
616169689Skan	case DT_SONAME:
617169689Skan	    /* Not used by the dynamic linker. */
618169689Skan	    break;
619169689Skan
620169689Skan	case DT_INIT:
62190075Sobrien	    obj->init = (InitFunc) (obj->relocbase + dynp->d_un.d_ptr);
62290075Sobrien	    break;
62390075Sobrien
62490075Sobrien	case DT_FINI:
62590075Sobrien	    obj->fini = (InitFunc) (obj->relocbase + dynp->d_un.d_ptr);
62690075Sobrien	    break;
62790075Sobrien
62890075Sobrien	case DT_DEBUG:
62990075Sobrien	    /* XXX - not implemented yet */
63090075Sobrien	    dbg("Filling in DT_DEBUG entry");
63190075Sobrien	    ((Elf_Dyn*)dynp)->d_un.d_ptr = (Elf_Addr) &r_debug;
63290075Sobrien	    break;
63390075Sobrien
63490075Sobrien	default:
635132718Skan	    dbg("Ignoring d_tag %d = %#x", dynp->d_tag, dynp->d_tag);
63690075Sobrien	    break;
63790075Sobrien	}
63890075Sobrien    }
63990075Sobrien
64090075Sobrien    obj->traced = false;
64190075Sobrien
64290075Sobrien    if (plttype == DT_RELA) {
643132718Skan	obj->pltrela = (const Elf_Rela *) obj->pltrel;
64490075Sobrien	obj->pltrel = NULL;
64590075Sobrien	obj->pltrelasize = obj->pltrelsize;
64690075Sobrien	obj->pltrelsize = 0;
64790075Sobrien    }
64890075Sobrien
64990075Sobrien    if (dyn_rpath != NULL)
65090075Sobrien	obj->rpath = obj->strtab + dyn_rpath->d_un.d_val;
651132718Skan}
65290075Sobrien
65390075Sobrien/*
65490075Sobrien * Process a shared object's program header.  This is used only for the
65590075Sobrien * main program, when the kernel has already loaded the main program
656117395Skan * into memory before calling the dynamic linker.  It creates and
657169689Skan * returns an Obj_Entry structure.
658169689Skan */
659169689Skanstatic Obj_Entry *
66090075Sobriendigest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry, const char *path)
661169689Skan{
662132718Skan    Obj_Entry *obj;
663132718Skan    const Elf_Phdr *phlimit = phdr + phnum;
66490075Sobrien    const Elf_Phdr *ph;
665117395Skan    int nsegs = 0;
66690075Sobrien
667117395Skan    obj = obj_new();
668117395Skan    for (ph = phdr;  ph < phlimit;  ph++) {
669117395Skan	switch (ph->p_type) {
670117395Skan
671132718Skan	case PT_PHDR:
67290075Sobrien	    if ((const Elf_Phdr *)ph->p_vaddr != phdr) {
673169689Skan		_rtld_error("%s: invalid PT_PHDR", path);
674169689Skan		return NULL;
675169689Skan	    }
676169689Skan	    obj->phdr = (const Elf_Phdr *) ph->p_vaddr;
677132718Skan	    obj->phsize = ph->p_memsz;
678132718Skan	    break;
67990075Sobrien
680117395Skan	case PT_INTERP:
68190075Sobrien	    obj->interp = (const char *) ph->p_vaddr;
682132718Skan	    break;
683132718Skan
684132718Skan	case PT_LOAD:
68590075Sobrien	    if (nsegs >= 2) {
686117395Skan		_rtld_error("%s: too many PT_LOAD segments", path);
687117395Skan		return NULL;
688117395Skan	    }
689169689Skan	    if (nsegs == 0) {	/* First load segment */
690117395Skan		obj->vaddrbase = trunc_page(ph->p_vaddr);
691117395Skan		obj->mapbase = (caddr_t) obj->vaddrbase;
692117395Skan		obj->relocbase = obj->mapbase - obj->vaddrbase;
693117395Skan		obj->textsize = round_page(ph->p_vaddr + ph->p_memsz) -
694117395Skan		  obj->vaddrbase;
695117395Skan	    } else {		/* Last load segment */
696117395Skan		obj->mapsize = round_page(ph->p_vaddr + ph->p_memsz) -
697169689Skan		  obj->vaddrbase;
698169689Skan	    }
699169689Skan	    nsegs++;
700169689Skan	    break;
701169689Skan
702169689Skan	case PT_DYNAMIC:
703117395Skan	    obj->dynamic = (const Elf_Dyn *) ph->p_vaddr;
704117395Skan	    break;
705117395Skan	}
706117395Skan    }
707117395Skan    if (nsegs < 2) {
708117395Skan	_rtld_error("%s: too few PT_LOAD segments", path);
709117395Skan	return NULL;
710117395Skan    }
711117395Skan
71290075Sobrien    obj->entry = entry;
713132718Skan    return obj;
71490075Sobrien}
715132718Skan
716169689Skanstatic Obj_Entry *
717169689Skandlcheck(void *handle)
718169689Skan{
719169689Skan    Obj_Entry *obj;
720117395Skan
721117395Skan    for (obj = obj_list;  obj != NULL;  obj = obj->next)
722117395Skan	if (obj == (Obj_Entry *) handle)
723102780Skan	    break;
724117395Skan
725117395Skan    if (obj == NULL || obj->refcount == 0 || obj->dl_refcount == 0) {
726102780Skan	_rtld_error("Invalid shared object handle %p", handle);
727117395Skan	return NULL;
728169689Skan    }
729169689Skan    return obj;
730169689Skan}
731169689Skan
732169689Skan/*
733169689Skan * If the given object is already in the donelist, return true.  Otherwise
734169689Skan * add the object to the list and return false.
735169689Skan */
736169689Skanstatic bool
737169689Skandonelist_check(DoneList *dlp, const Obj_Entry *obj)
738117395Skan{
739117395Skan    unsigned int i;
740117395Skan
741117395Skan    for (i = 0;  i < dlp->num_used;  i++)
742132718Skan	if (dlp->objs[i] == obj)
743132718Skan	    return true;
744132718Skan    /*
745132718Skan     * Our donelist allocation should always be sufficient.  But if
746132718Skan     * our threads locking isn't working properly, more shared objects
747132718Skan     * could have been loaded since we allocated the list.  That should
748117395Skan     * never happen, but we'll handle it properly just in case it does.
749132718Skan     */
750117395Skan    if (dlp->num_used < dlp->num_alloc)
751117395Skan	dlp->objs[dlp->num_used++] = obj;
752117395Skan    return false;
753117395Skan}
75490075Sobrien
755132718Skan/*
756117395Skan * Hash function for symbol table lookup.  Don't even think about changing
757117395Skan * this.  It is specified by the System V ABI.
758117395Skan */
759117395Skanunsigned long
760117395Skanelf_hash(const char *name)
76118334Speter{
762117395Skan    const unsigned char *p = (const unsigned char *) name;
763117395Skan    unsigned long h = 0;
764117395Skan    unsigned long g;
765117395Skan
766117395Skan    while (*p != '\0') {
767117395Skan	h = (h << 4) + *p++;
768117395Skan	if ((g = h & 0xf0000000) != 0)
769117395Skan	    h ^= g >> 24;
770132718Skan	h &= ~g;
771117395Skan    }
772117395Skan    return h;
773117395Skan}
774117395Skan
775117395Skan/*
776117395Skan * Find the library with the given name, and return its full pathname.
777117395Skan * The returned string is dynamically allocated.  Generates an error
778169689Skan * message and returns NULL if the library cannot be found.
779169689Skan *
780169689Skan * If the second argument is non-NULL, then it refers to an already-
781169689Skan * loaded shared object, whose library search path will be searched.
782169689Skan *
783169689Skan * The search order is:
78490075Sobrien *   rpath in the referencing file
78590075Sobrien *   LD_LIBRARY_PATH
78690075Sobrien *   ldconfig hints
78790075Sobrien *   /usr/lib
78890075Sobrien */
789169689Skanstatic char *
79090075Sobrienfind_library(const char *name, const Obj_Entry *refobj)
791169689Skan{
79290075Sobrien    char *pathname;
79318334Speter
794132718Skan    if (strchr(name, '/') != NULL) {	/* Hard coded pathname */
795132718Skan	if (name[0] != '/' && !trust) {
796132718Skan	    _rtld_error("Absolute pathname required for shared object \"%s\"",
797132718Skan	      name);
798132718Skan	    return NULL;
799132718Skan	}
800132718Skan	return xstrdup(name);
801132718Skan    }
802132718Skan
803132718Skan    dbg(" Searching for \"%s\"", name);
804132718Skan
805132718Skan    if ((refobj != NULL &&
806132718Skan      (pathname = search_library_path(name, refobj->rpath)) != NULL) ||
807132718Skan      (pathname = search_library_path(name, ld_library_path)) != NULL ||
808132718Skan      (pathname = search_library_path(name, gethints())) != NULL ||
809132718Skan      (pathname = search_library_path(name, STANDARD_LIBRARY_PATH)) != NULL)
810132718Skan	return pathname;
811132718Skan
812132718Skan    _rtld_error("Shared object \"%s\" not found", name);
81390075Sobrien    return NULL;
81490075Sobrien}
81590075Sobrien
81690075Sobrien/*
81718334Speter * Given a symbol number in a referencing object, find the corresponding
81890075Sobrien * definition of the symbol.  Returns a pointer to the symbol, or NULL if
819132718Skan * no definition was found.  Returns a pointer to the Obj_Entry of the
82090075Sobrien * defining object via the reference parameter DEFOBJ_OUT.
82190075Sobrien */
82290075Sobrienconst Elf_Sym *
82390075Sobrienfind_symdef(unsigned long symnum, const Obj_Entry *refobj,
82490075Sobrien    const Obj_Entry **defobj_out, bool in_plt)
82590075Sobrien{
82690075Sobrien    const Elf_Sym *ref;
82790075Sobrien    const Elf_Sym *def;
82890075Sobrien    const Obj_Entry *defobj;
829117395Skan    const char *name;
830169689Skan    unsigned long hash;
83118334Speter
83290075Sobrien    ref = refobj->symtab + symnum;
83390075Sobrien    name = refobj->strtab + ref->st_name;
83490075Sobrien    hash = elf_hash(name);
83590075Sobrien    defobj = NULL;
83690075Sobrien
83790075Sobrien    def = symlook_default(name, hash, refobj, &defobj, in_plt);
83890075Sobrien
83990075Sobrien    /*
84090075Sobrien     * If we found no definition and the reference is weak, treat the
84190075Sobrien     * symbol as having the value zero.
84218334Speter     */
84390075Sobrien    if (def == NULL && ELF_ST_BIND(ref->st_info) == STB_WEAK) {
84490075Sobrien	def = &sym_zero;
84590075Sobrien	defobj = obj_main;
84690075Sobrien    }
84790075Sobrien
84890075Sobrien    if (def != NULL)
84990075Sobrien	*defobj_out = defobj;
85090075Sobrien    else
85190075Sobrien	_rtld_error("%s: Undefined symbol \"%s\"", refobj->path, name);
85290075Sobrien    return def;
85390075Sobrien}
85490075Sobrien
85590075Sobrien/*
856169689Skan * Return the search path from the ldconfig hints file, reading it if
857169689Skan * necessary.  Returns NULL if there are problems with the hints file,
858169689Skan * or if the search path there is empty.
859169689Skan */
860169689Skanstatic const char *
861169689Skangethints(void)
862169689Skan{
863169689Skan    static char *hints;
864169689Skan
865169689Skan    if (hints == NULL) {
86690075Sobrien	int fd;
86790075Sobrien	struct elfhints_hdr hdr;
86890075Sobrien	char *p;
86990075Sobrien
87090075Sobrien	/* Keep from trying again in case the hints file is bad. */
87190075Sobrien	hints = "";
872169689Skan
87390075Sobrien	if ((fd = open(_PATH_ELF_HINTS, O_RDONLY)) == -1)
87490075Sobrien	    return NULL;
87590075Sobrien	if (read(fd, &hdr, sizeof hdr) != sizeof hdr ||
87690075Sobrien	  hdr.magic != ELFHINTS_MAGIC ||
87790075Sobrien	  hdr.version != 1) {
87890075Sobrien	    close(fd);
879132718Skan	    return NULL;
880117395Skan	}
881169689Skan	p = xmalloc(hdr.dirlistlen + 1);
882169689Skan	if (lseek(fd, hdr.strtab + hdr.dirlist, SEEK_SET) == -1 ||
88390075Sobrien	  read(fd, p, hdr.dirlistlen + 1) != hdr.dirlistlen + 1) {
88490075Sobrien	    free(p);
88590075Sobrien	    close(fd);
886132718Skan	    return NULL;
88790075Sobrien	}
88890075Sobrien	hints = p;
88990075Sobrien	close(fd);
89090075Sobrien    }
891169689Skan    return hints[0] != '\0' ? hints : NULL;
892169689Skan}
89390075Sobrien
894169689Skanstatic void
895169689Skaninit_dag(Obj_Entry *root)
89690075Sobrien{
89790075Sobrien    DoneList donelist;
89890075Sobrien
89990075Sobrien    donelist_init(&donelist);
90090075Sobrien    init_dag1(root, root, &donelist);
90118334Speter}
90290075Sobrien
903169689Skanstatic void
904169689Skaninit_dag1(Obj_Entry *root, Obj_Entry *obj, DoneList *dlp)
905169689Skan{
906169689Skan    const Needed_Entry *needed;
90790075Sobrien
90890075Sobrien    if (donelist_check(dlp, obj))
90990075Sobrien	return;
91090075Sobrien    objlist_push_tail(&obj->dldags, root);
911169689Skan    objlist_push_tail(&root->dagmembers, obj);
91290075Sobrien    for (needed = obj->needed;  needed != NULL;  needed = needed->next)
91390075Sobrien	if (needed->obj != NULL)
91490075Sobrien	    init_dag1(root, needed->obj, dlp);
91590075Sobrien}
91690075Sobrien
91718334Speter/*
91818334Speter * Initialize the dynamic linker.  The argument is the address at which
91990075Sobrien * the dynamic linker has been mapped into memory.  The primary task of
92090075Sobrien * this function is to relocate the dynamic linker.
92190075Sobrien */
922169689Skanstatic void
923169689Skaninit_rtld(caddr_t mapbase)
924169689Skan{
92590075Sobrien    /*
92618334Speter     * Conjure up an Obj_Entry structure for the dynamic linker.
92790075Sobrien     *
92818334Speter     * The "path" member is supposed to be dynamically-allocated, but we
92918334Speter     * aren't yet initialized sufficiently to do that.  Below we will
93090075Sobrien     * replace the static version with a dynamically-allocated copy.
93190075Sobrien     */
93218334Speter    obj_rtld.path = PATH_RTLD;
93390075Sobrien    obj_rtld.rtld = true;
93418334Speter    obj_rtld.mapbase = mapbase;
93590075Sobrien#ifdef PIC
93690075Sobrien    obj_rtld.relocbase = mapbase;
93790075Sobrien#endif
93890075Sobrien    if (&_DYNAMIC != 0) {
939169689Skan	obj_rtld.dynamic = rtld_dynamic(&obj_rtld);
94090075Sobrien	digest_dynamic(&obj_rtld);
94190075Sobrien	assert(obj_rtld.needed == NULL);
94290075Sobrien	assert(!obj_rtld.textrel);
94390075Sobrien
94490075Sobrien	/*
94590075Sobrien	 * Temporarily put the dynamic linker entry into the object list, so
94690075Sobrien	 * that symbols can be found.
94790075Sobrien	 */
94890075Sobrien	obj_list = &obj_rtld;
94990075Sobrien	obj_tail = &obj_rtld.next;
95090075Sobrien	obj_count = 1;
95190075Sobrien
95290075Sobrien	relocate_objects(&obj_rtld, true);
95390075Sobrien    }
95490075Sobrien
95590075Sobrien    /* Make the object list empty again. */
956102780Skan    obj_list = NULL;
957102780Skan    obj_tail = &obj_list;
958102780Skan    obj_count = 0;
959102780Skan
960102780Skan    /* Replace the path with a dynamically allocated copy. */
96190075Sobrien    obj_rtld.path = xstrdup(obj_rtld.path);
96290075Sobrien
963132718Skan    r_debug.r_brk = r_debug_state;
96490075Sobrien    r_debug.r_state = RT_CONSISTENT;
965102780Skan}
966117395Skan
96718334Speter/*
96890075Sobrien * Add the init functions from a needed object list (and its recursive
96918334Speter * needed objects) to "list".  This is not used directly; it is a helper
97090075Sobrien * function for initlist_add_objects().  The write lock must be held
97190075Sobrien * when this function is called.
972169689Skan */
97390075Sobrienstatic void
97490075Sobrieninitlist_add_neededs(Needed_Entry *needed, Objlist *list)
97590075Sobrien{
97690075Sobrien    /* Recursively process the successor needed objects. */
97790075Sobrien    if (needed->next != NULL)
97890075Sobrien	initlist_add_neededs(needed->next, list);
97990075Sobrien
98090075Sobrien    /* Process the current needed object. */
98190075Sobrien    if (needed->obj != NULL)
98290075Sobrien	initlist_add_objects(needed->obj, &needed->obj->next, list);
98390075Sobrien}
98490075Sobrien
98590075Sobrien/*
98690075Sobrien * Scan all of the DAGs rooted in the range of objects from "obj" to
98718334Speter * "tail" and add their init functions to "list".  This recurses over
988102780Skan * the DAGs and ensure the proper init ordering such that each object's
989102780Skan * needed libraries are initialized before the object itself.  At the
990102780Skan * same time, this function adds the objects to the global finalization
991102780Skan * list "list_fini" in the opposite order.  The write lock must be
992102780Skan * held when this function is called.
99390075Sobrien */
99490075Sobrienstatic void
99590075Sobrieninitlist_add_objects(Obj_Entry *obj, Obj_Entry **tail, Objlist *list)
99690075Sobrien{
99790075Sobrien    if (obj->init_done)
99890075Sobrien	return;
99990075Sobrien    obj->init_done = true;
100090075Sobrien
100190075Sobrien    /* Recursively process the successor objects. */
1002132718Skan    if (&obj->next != tail)
100390075Sobrien	initlist_add_objects(obj->next, tail, list);
1004102780Skan
1005117395Skan    /* Recursively process the needed objects. */
100690075Sobrien    if (obj->needed != NULL)
100790075Sobrien	initlist_add_neededs(obj->needed, list);
100890075Sobrien
1009117395Skan    /* Add the object to the init list. */
1010117395Skan    if (obj->init != NULL)
1011117395Skan	objlist_push_tail(list, obj);
1012117395Skan
1013132718Skan    /* Add the object to the global fini list in the reverse order. */
1014117395Skan    if (obj->fini != NULL)
1015117395Skan	objlist_push_head(&list_fini, obj);
1016117395Skan}
1017132718Skan
1018132718Skanstatic bool
1019117395Skanis_exported(const Elf_Sym *def)
1020132718Skan{
1021117395Skan    func_ptr_type value;
1022117395Skan    const func_ptr_type *p;
1023169689Skan
102496263Sobrien    value = (func_ptr_type)(obj_rtld.relocbase + def->st_value);
1025117395Skan    for (p = exports;  *p != NULL;  p++)
1026169689Skan	if (*p == value)
102796263Sobrien	    return true;
1028169689Skan    return false;
1029169689Skan}
1030117395Skan
1031117395Skan/*
1032117395Skan * Given a shared object, traverse its list of needed objects, and load
1033117395Skan * each of them.  Returns 0 on success.  Generates an error message and
1034117395Skan * returns -1 on failure.
1035117395Skan */
1036117395Skanstatic int
1037117395Skanload_needed_objects(Obj_Entry *first)
1038117395Skan{
1039117395Skan    Obj_Entry *obj;
1040132718Skan
1041132718Skan    for (obj = first;  obj != NULL;  obj = obj->next) {
1042169689Skan	Needed_Entry *needed;
1043117395Skan
1044117395Skan	for (needed = obj->needed;  needed != NULL;  needed = needed->next) {
1045117395Skan	    const char *name = obj->strtab + needed->name;
1046117395Skan	    char *path = find_library(name, obj);
1047169689Skan
104896263Sobrien	    needed->obj = NULL;
1049117395Skan	    if (path == NULL && !ld_tracing)
1050117395Skan		return -1;
1051169689Skan
1052169689Skan	    if (path) {
1053117395Skan		needed->obj = load_object(path);
1054132718Skan		if (needed->obj == NULL && !ld_tracing)
1055169689Skan		    return -1;		/* XXX - cleanup */
1056169689Skan	    }
1057117395Skan	}
1058169689Skan    }
1059169689Skan
1060169689Skan    return 0;
1061169689Skan}
1062117395Skan
1063169689Skanstatic int
1064169689Skanload_preload_objects(void)
1065117395Skan{
1066117395Skan    char *p = ld_preload;
1067117395Skan    static const char delim[] = " \t:;";
1068132718Skan
1069132718Skan    if (p == NULL)
1070117395Skan	return NULL;
107196263Sobrien
1072117395Skan    p += strspn(p, delim);
1073117395Skan    while (*p != '\0') {
1074117395Skan	size_t len = strcspn(p, delim);
1075117395Skan	char *path;
1076117395Skan	char savech;
1077117395Skan
1078117395Skan	savech = p[len];
1079132718Skan	p[len] = '\0';
1080169689Skan	if ((path = find_library(p, NULL)) == NULL)
1081169689Skan	    return -1;
1082117395Skan	if (load_object(path) == NULL)
1083117395Skan	    return -1;	/* XXX - cleanup */
1084132718Skan	p[len] = savech;
1085132718Skan	p += len;
1086132718Skan	p += strspn(p, delim);
1087117395Skan    }
1088132718Skan    return 0;
1089117395Skan}
1090117395Skan
1091169689Skan/*
1092132718Skan * Load a shared object into memory, if it is not already loaded.  The
1093117395Skan * argument must be a string allocated on the heap.  This function assumes
1094132718Skan * responsibility for freeing it when necessary.
1095117395Skan *
1096117395Skan * Returns a pointer to the Obj_Entry for the object.  Returns NULL
1097117395Skan * on failure.
1098117395Skan */
1099117395Skanstatic Obj_Entry *
1100132718Skanload_object(char *path)
1101117395Skan{
1102117395Skan    Obj_Entry *obj;
1103117395Skan    int fd = -1;
1104117395Skan    struct stat sb;
1105117395Skan
1106117395Skan    for (obj = obj_list->next;  obj != NULL;  obj = obj->next)
1107117395Skan	if (strcmp(obj->path, path) == 0)
1108117395Skan	    break;
1109117395Skan
1110117395Skan    /*
1111169689Skan     * If we didn't find a match by pathname, open the file and check
1112169689Skan     * again by device and inode.  This avoids false mismatches caused
1113132718Skan     * by multiple links or ".." in pathnames.
1114117395Skan     *
1115132718Skan     * To avoid a race, we open the file and use fstat() rather than
1116132718Skan     * using stat().
1117117395Skan     */
1118132718Skan    if (obj == NULL) {
1119117395Skan	if ((fd = open(path, O_RDONLY)) == -1) {
1120132718Skan	    _rtld_error("Cannot open \"%s\"", path);
1121117395Skan	    return NULL;
1122132718Skan	}
1123132718Skan	if (fstat(fd, &sb) == -1) {
1124132718Skan	    _rtld_error("Cannot fstat \"%s\"", path);
1125169689Skan	    close(fd);
1126169689Skan	    return NULL;
1127169689Skan	}
1128169689Skan	for (obj = obj_list->next;  obj != NULL;  obj = obj->next) {
1129117395Skan	    if (obj->ino == sb.st_ino && obj->dev == sb.st_dev) {
1130169689Skan		close(fd);
1131169689Skan		break;
1132169689Skan	    }
1133169689Skan	}
1134169689Skan    }
1135169689Skan
1136117395Skan    if (obj == NULL) {	/* First use of this object, so we must map it in */
1137169689Skan	dbg("loading \"%s\"", path);
1138117395Skan	obj = map_object(fd, path, &sb);
1139117395Skan	close(fd);
1140117395Skan	if (obj == NULL) {
1141117395Skan	    free(path);
1142117395Skan	    return NULL;
1143132718Skan	}
1144117395Skan
1145117395Skan	obj->path = path;
1146117395Skan	digest_dynamic(obj);
1147117395Skan
114896263Sobrien	*obj_tail = obj;
114996263Sobrien	obj_tail = &obj->next;
115090075Sobrien	obj_count++;
115190075Sobrien	linkmap_add(obj);	/* for GDB */
115290075Sobrien
115390075Sobrien	dbg("  %p .. %p: %s", obj->mapbase,
115490075Sobrien	  obj->mapbase + obj->mapsize - 1, obj->path);
115590075Sobrien	if (obj->textrel)
115690075Sobrien	    dbg("  WARNING: %s has impure text", obj->path);
115790075Sobrien    } else
115890075Sobrien	free(path);
115990075Sobrien
116090075Sobrien    obj->refcount++;
116190075Sobrien    return obj;
116290075Sobrien}
1163169689Skan
116490075Sobrien/*
116590075Sobrien * Check for locking violations and die if one is found.
116690075Sobrien */
116790075Sobrienstatic void
116890075Sobrienlock_check(void)
116990075Sobrien{
1170169689Skan    int rcount, wcount;
1171169689Skan
1172169689Skan    rcount = lockinfo.rcount;
117390075Sobrien    wcount = lockinfo.wcount;
117490075Sobrien    assert(rcount >= 0);
117590075Sobrien    assert(wcount >= 0);
117690075Sobrien    if (wcount > 1 || (wcount != 0 && rcount != 0)) {
1177169689Skan	_rtld_error("Application locking error: %d readers and %d writers"
1178169689Skan	  " in dynamic linker.  See DLLOCKINIT(3) in manual pages.",
117996263Sobrien	  rcount, wcount);
118090075Sobrien	die();
118190075Sobrien    }
118290075Sobrien}
118390075Sobrien
118490075Sobrienstatic Obj_Entry *
118590075Sobrienobj_from_addr(const void *addr)
118690075Sobrien{
118790075Sobrien    unsigned long endhash;
118890075Sobrien    Obj_Entry *obj;
1189169689Skan
1190169689Skan    endhash = elf_hash(END_SYM);
119118334Speter    for (obj = obj_list;  obj != NULL;  obj = obj->next) {
119290075Sobrien	const Elf_Sym *endsym;
119390075Sobrien
1194169689Skan	if (addr < (void *) obj->mapbase)
1195169689Skan	    continue;
1196169689Skan	if ((endsym = symlook_obj(END_SYM, endhash, obj, true)) == NULL)
119790075Sobrien	    continue;	/* No "end" symbol?! */
119890075Sobrien	if (addr < (void *) (obj->relocbase + endsym->st_value))
119990075Sobrien	    return obj;
1200132718Skan    }
120118334Speter    return NULL;
1202169689Skan}
1203169689Skan
1204169689Skan/*
1205169689Skan * Call the finalization functions for each of the objects in "list"
1206169689Skan * which are unreferenced.  All of the objects are expected to have
1207169689Skan * non-NULL fini functions.
1208169689Skan */
1209169689Skanstatic void
1210169689Skanobjlist_call_fini(Objlist *list)
1211169689Skan{
1212169689Skan    Objlist_Entry *elm;
1213169689Skan    char *saved_msg;
1214169689Skan
1215169689Skan    /*
1216169689Skan     * Preserve the current error message since a fini function might
121718334Speter     * call into the dynamic linker and overwrite it.
121818334Speter     */
121990075Sobrien    saved_msg = errmsg_save();
122090075Sobrien    STAILQ_FOREACH(elm, list, link) {
122118334Speter	if (elm->obj->refcount == 0) {
122290075Sobrien	    dbg("calling fini function for %s", elm->obj->path);
122318334Speter	    (*elm->obj->fini)();
122490075Sobrien	}
122590075Sobrien    }
1226132718Skan    errmsg_restore(saved_msg);
122790075Sobrien}
122890075Sobrien
1229132718Skan/*
123090075Sobrien * Call the initialization functions for each of the objects in
123190075Sobrien * "list".  All of the objects are expected to have non-NULL init
123290075Sobrien * functions.
123390075Sobrien */
123490075Sobrienstatic void
123590075Sobrienobjlist_call_init(Objlist *list)
123690075Sobrien{
123790075Sobrien    Objlist_Entry *elm;
123818334Speter    char *saved_msg;
123918334Speter
124090075Sobrien    /*
124190075Sobrien     * Preserve the current error message since an init function might
124218334Speter     * call into the dynamic linker and overwrite it.
124390075Sobrien     */
124418334Speter    saved_msg = errmsg_save();
124518334Speter    STAILQ_FOREACH(elm, list, link) {
124690075Sobrien	dbg("calling init function for %s", elm->obj->path);
124790075Sobrien	(*elm->obj->init)();
124890075Sobrien    }
124990075Sobrien    errmsg_restore(saved_msg);
125090075Sobrien}
125190075Sobrien
125290075Sobrienstatic void
125390075Sobrienobjlist_clear(Objlist *list)
125490075Sobrien{
1255132718Skan    Objlist_Entry *elm;
125690075Sobrien
1257169689Skan    while (!STAILQ_EMPTY(list)) {
1258169689Skan	elm = STAILQ_FIRST(list);
125918334Speter	STAILQ_REMOVE_HEAD(list, link);
1260169689Skan	free(elm);
126190075Sobrien    }
1262169689Skan}
1263117395Skan
126490075Sobrienstatic Objlist_Entry *
126590075Sobrienobjlist_find(Objlist *list, const Obj_Entry *obj)
126690075Sobrien{
126790075Sobrien    Objlist_Entry *elm;
126890075Sobrien
126990075Sobrien    STAILQ_FOREACH(elm, list, link)
127090075Sobrien	if (elm->obj == obj)
127190075Sobrien	    return elm;
127290075Sobrien    return NULL;
127390075Sobrien}
127490075Sobrien
127590075Sobrienstatic void
127690075Sobrienobjlist_init(Objlist *list)
127790075Sobrien{
127890075Sobrien    STAILQ_INIT(list);
127990075Sobrien}
128090075Sobrien
128190075Sobrienstatic void
128290075Sobrienobjlist_push_head(Objlist *list, Obj_Entry *obj)
128390075Sobrien{
128490075Sobrien    Objlist_Entry *elm;
128590075Sobrien
128690075Sobrien    elm = NEW(Objlist_Entry);
128790075Sobrien    elm->obj = obj;
128890075Sobrien    STAILQ_INSERT_HEAD(list, elm, link);
128990075Sobrien}
129090075Sobrien
129190075Sobrienstatic void
1292169689Skanobjlist_push_tail(Objlist *list, Obj_Entry *obj)
1293169689Skan{
129490075Sobrien    Objlist_Entry *elm;
1295169689Skan
1296169689Skan    elm = NEW(Objlist_Entry);
129790075Sobrien    elm->obj = obj;
129890075Sobrien    STAILQ_INSERT_TAIL(list, elm, link);
129990075Sobrien}
130090075Sobrien
1301169689Skanstatic void
1302169689Skanobjlist_remove(Objlist *list, Obj_Entry *obj)
130390075Sobrien{
1304169689Skan    Objlist_Entry *elm;
130590075Sobrien
130690075Sobrien    if ((elm = objlist_find(list, obj)) != NULL) {
130790075Sobrien	STAILQ_REMOVE(list, elm, Struct_Objlist_Entry, link);
130818334Speter	free(elm);
130918334Speter    }
131090075Sobrien}
131190075Sobrien
131290075Sobrien/*
1313132718Skan * Remove all of the unreferenced objects from "list".
131418334Speter */
131590075Sobrienstatic void
131690075Sobrienobjlist_remove_unref(Objlist *list)
131718334Speter{
131890075Sobrien    Objlist newlist;
131990075Sobrien    Objlist_Entry *elm;
132090075Sobrien
132190075Sobrien    STAILQ_INIT(&newlist);
132290075Sobrien    while (!STAILQ_EMPTY(list)) {
132318334Speter	elm = STAILQ_FIRST(list);
132490075Sobrien	STAILQ_REMOVE_HEAD(list, link);
132590075Sobrien	if (elm->obj->refcount == 0)
132650397Sobrien	    free(elm);
132790075Sobrien	else
132890075Sobrien	    STAILQ_INSERT_TAIL(&newlist, elm, link);
132990075Sobrien    }
133090075Sobrien    *list = newlist;
133190075Sobrien}
133290075Sobrien
133318334Speter/*
133418334Speter * Relocate newly-loaded shared objects.  The argument is a pointer to
133590075Sobrien * the Obj_Entry for the first such object.  All objects from the first
133690075Sobrien * to the end of the list of objects are relocated.  Returns 0 on success,
1337132718Skan * or -1 on failure.
1338132718Skan */
1339132718Skanstatic int
134090075Sobrienrelocate_objects(Obj_Entry *first, bool bind_now)
134190075Sobrien{
134290075Sobrien    Obj_Entry *obj;
134390075Sobrien
134418334Speter    for (obj = first;  obj != NULL;  obj = obj->next) {
134590075Sobrien	if (obj != &obj_rtld)
134690075Sobrien	    dbg("relocating \"%s\"", obj->path);
134790075Sobrien	if (obj->nbuckets == 0 || obj->nchains == 0 || obj->buckets == NULL ||
134890075Sobrien	    obj->symtab == NULL || obj->strtab == NULL) {
134990075Sobrien	    _rtld_error("%s: Shared object has no run-time symbol table",
135018334Speter	      obj->path);
135190075Sobrien	    return -1;
135290075Sobrien	}
135390075Sobrien
135418334Speter	if (obj->textrel) {
1355117395Skan	    /* There are relocations to the write-protected text segment. */
135690075Sobrien	    if (mprotect(obj->mapbase, obj->textsize,
135790075Sobrien	      PROT_READ|PROT_WRITE|PROT_EXEC) == -1) {
135890075Sobrien		_rtld_error("%s: Cannot write-enable text segment: %s",
135918334Speter		  obj->path, strerror(errno));
1360169689Skan		return -1;
1361169689Skan	    }
1362169689Skan	}
1363169689Skan
1364169689Skan	/* Process the non-PLT relocations. */
1365169689Skan	if (reloc_non_plt(obj, &obj_rtld))
136690075Sobrien		return -1;
136718334Speter
136890075Sobrien	if (obj->textrel) {	/* Re-protected the text segment. */
136918334Speter	    if (mprotect(obj->mapbase, obj->textsize,
137090075Sobrien	      PROT_READ|PROT_EXEC) == -1) {
137190075Sobrien		_rtld_error("%s: Cannot write-protect text segment: %s",
137290075Sobrien		  obj->path, strerror(errno));
137390075Sobrien		return -1;
137490075Sobrien	    }
137590075Sobrien	}
137690075Sobrien
137790075Sobrien	/* Process the PLT relocations. */
137890075Sobrien	if (reloc_plt(obj) == -1)
137990075Sobrien	    return -1;
138090075Sobrien	/* Relocate the jump slots if we are doing immediate binding. */
138190075Sobrien	if (bind_now)
138290075Sobrien	    if (reloc_jmpslots(obj) == -1)
138390075Sobrien		return -1;
138490075Sobrien
138590075Sobrien
138690075Sobrien	/*
138790075Sobrien	 * Set up the magic number and version in the Obj_Entry.  These
1388132718Skan	 * were checked in the crt1.o from the original ElfKit, so we
138990075Sobrien	 * set them for backward compatibility.
139090075Sobrien	 */
139190075Sobrien	obj->magic = RTLD_MAGIC;
139290075Sobrien	obj->version = RTLD_VERSION;
139390075Sobrien
139490075Sobrien	/* Set the special PLT or GOT entries. */
139590075Sobrien	init_pltgot(obj);
139690075Sobrien    }
139790075Sobrien
139890075Sobrien    return 0;
139990075Sobrien}
140090075Sobrien
1401169689Skan/*
1402169689Skan * Cleanup procedure.  It will be called (by the atexit mechanism) just
1403169689Skan * before the process exits.
1404169689Skan */
1405169689Skanstatic void
1406169689Skanrtld_exit(void)
1407169689Skan{
1408169689Skan    Obj_Entry *obj;
1409169689Skan
141090075Sobrien    dbg("rtld_exit()");
141190075Sobrien    wlock_acquire();
141290075Sobrien    /* Clear all the reference counts so the fini functions will be called. */
141318334Speter    for (obj = obj_list;  obj != NULL;  obj = obj->next)
141490075Sobrien	obj->refcount = 0;
141590075Sobrien    wlock_release();
141618334Speter    objlist_call_fini(&list_fini);
141718334Speter    /* No need to remove the items from the list, since we are exiting. */
141890075Sobrien}
141990075Sobrien
142090075Sobrienstatic char *
142190075Sobriensearch_library_path(const char *name, const char *path)
142290075Sobrien{
142390075Sobrien    size_t namelen = strlen(name);
142490075Sobrien    const char *p = path;
1425169689Skan
1426169689Skan    if (p == NULL)
1427169689Skan	return NULL;
142890075Sobrien
142990075Sobrien    p += strspn(p, ":;");
143090075Sobrien    while (*p != '\0') {
143190075Sobrien	size_t len = strcspn(p, ":;");
1432169689Skan
1433169689Skan	if (*p == '/' || trust) {
143490075Sobrien	    char *pathname;
143590075Sobrien	    const char *dir = p;
143690075Sobrien	    size_t dirlen = len;
143790075Sobrien
143890075Sobrien	    pathname = xmalloc(dirlen + 1 + namelen + 1);
143990075Sobrien	    strncpy(pathname, dir, dirlen);
144090075Sobrien	    pathname[dirlen] = '/';
144190075Sobrien	    strcpy(pathname + dirlen + 1, name);
144290075Sobrien
144390075Sobrien	    dbg("  Trying \"%s\"", pathname);
144490075Sobrien	    if (access(pathname, F_OK) == 0)		/* We found it */
144590075Sobrien		return pathname;
144690075Sobrien
144790075Sobrien	    free(pathname);
144890075Sobrien	}
144990075Sobrien	p += len;
145090075Sobrien	p += strspn(p, ":;");
145190075Sobrien    }
145290075Sobrien
145390075Sobrien    return NULL;
145490075Sobrien}
145590075Sobrien
145690075Sobrienint
145790075Sobriendlclose(void *handle)
145890075Sobrien{
145990075Sobrien    Obj_Entry *root;
146090075Sobrien
146190075Sobrien    wlock_acquire();
146290075Sobrien    root = dlcheck(handle);
146390075Sobrien    if (root == NULL) {
146490075Sobrien	wlock_release();
146590075Sobrien	return -1;
146690075Sobrien    }
146718334Speter
146890075Sobrien    /* Unreference the object and its dependencies. */
146990075Sobrien    root->dl_refcount--;
147090075Sobrien    unref_dag(root);
1471117395Skan
1472117395Skan    if (root->refcount == 0) {
1473117395Skan	/*
147490075Sobrien	 * The object is no longer referenced, so we must unload it.
147590075Sobrien	 * First, call the fini functions with no locks held.
1476132718Skan	 */
147790075Sobrien	wlock_release();
1478169689Skan	objlist_call_fini(&list_fini);
1479169689Skan	wlock_acquire();
148090075Sobrien	objlist_remove_unref(&list_fini);
148190075Sobrien
148290075Sobrien	/* Finish cleaning up the newly-unreferenced objects. */
148390075Sobrien	GDB_STATE(RT_DELETE,&root->linkmap);
148490075Sobrien	unload_object(root);
148590075Sobrien	GDB_STATE(RT_CONSISTENT,NULL);
148690075Sobrien    }
148790075Sobrien    wlock_release();
148890075Sobrien    return 0;
1489169689Skan}
1490169689Skan
1491169689Skanconst char *
1492169689Skandlerror(void)
1493169689Skan{
1494169689Skan    char *msg = error_message;
149590075Sobrien    error_message = NULL;
149690075Sobrien    return msg;
149790075Sobrien}
149890075Sobrien
149990075Sobrien/*
150090075Sobrien * This function is deprecated and has no effect.
150190075Sobrien */
150290075Sobrienvoid
150390075Sobriendllockinit(void *context,
1504117395Skan	   void *(*lock_create)(void *context),
1505117395Skan           void (*rlock_acquire)(void *lock),
150690075Sobrien           void (*wlock_acquire)(void *lock),
150718334Speter           void (*lock_release)(void *lock),
1508132718Skan           void (*lock_destroy)(void *lock),
1509132718Skan	   void (*context_destroy)(void *context))
1510132718Skan{
1511132718Skan    static void *cur_context;
1512132718Skan    static void (*cur_context_destroy)(void *);
1513132718Skan
1514132718Skan    /* Just destroy the context from the previous call, if necessary. */
1515132718Skan    if (cur_context_destroy != NULL)
1516132718Skan	cur_context_destroy(cur_context);
1517132718Skan    cur_context = context;
1518132718Skan    cur_context_destroy = context_destroy;
1519132718Skan}
1520132718Skan
1521132718Skanvoid *
1522132718Skandlopen(const char *name, int mode)
1523132718Skan{
1524132718Skan    Obj_Entry **old_obj_tail;
1525132718Skan    Obj_Entry *obj;
1526132718Skan    Objlist initlist;
1527132718Skan
1528132718Skan    objlist_init(&initlist);
1529132718Skan
1530132718Skan    wlock_acquire();
1531132718Skan    GDB_STATE(RT_ADD,NULL);
1532132718Skan
1533132718Skan    old_obj_tail = obj_tail;
1534132718Skan    obj = NULL;
1535132718Skan    if (name == NULL) {
1536132718Skan	obj = obj_main;
1537132718Skan	obj->refcount++;
1538132718Skan    } else {
1539132718Skan	char *path = find_library(name, obj_main);
1540132718Skan	if (path != NULL)
1541132718Skan	    obj = load_object(path);
1542132718Skan    }
1543132718Skan
1544132718Skan    if (obj) {
154518334Speter	obj->dl_refcount++;
154618334Speter	if (mode & RTLD_GLOBAL && objlist_find(&list_global, obj) == NULL)
154718334Speter	    objlist_push_tail(&list_global, obj);
154818334Speter	mode &= RTLD_MODEMASK;
154918334Speter	if (*old_obj_tail != NULL) {		/* We loaded something new. */
155018334Speter	    assert(*old_obj_tail == obj);
155118334Speter
155218334Speter	    if (load_needed_objects(obj) == -1 ||
155318334Speter	      (init_dag(obj), relocate_objects(obj, mode == RTLD_NOW)) == -1) {
155418334Speter		obj->dl_refcount--;
155518334Speter		unref_dag(obj);
1556132718Skan		if (obj->refcount == 0)
155718334Speter		    unload_object(obj);
1558169689Skan		obj = NULL;
155918334Speter	    } else {
1560169689Skan		/* Make list of init functions to call. */
1561169689Skan		initlist_add_objects(obj, &obj->next, &initlist);
1562169689Skan	    }
156318334Speter	}
156418334Speter    }
156518334Speter
156618334Speter    GDB_STATE(RT_CONSISTENT,obj ? &obj->linkmap : NULL);
156718334Speter
156818334Speter    /* Call the init functions with no locks held. */
156918334Speter    wlock_release();
157018334Speter    objlist_call_init(&initlist);
157118334Speter    wlock_acquire();
1572169689Skan    objlist_clear(&initlist);
157318334Speter    wlock_release();
157490075Sobrien    return obj;
157550397Sobrien}
157690075Sobrien
157750397Sobrienvoid *
157890075Sobriendlsym(void *handle, const char *name)
157990075Sobrien{
158018334Speter    const Obj_Entry *obj;
158118334Speter    unsigned long hash;
158218334Speter    const Elf_Sym *def;
158318334Speter    const Obj_Entry *defobj;
1584169689Skan
158518334Speter    hash = elf_hash(name);
158618334Speter    def = NULL;
158718334Speter    defobj = NULL;
158890075Sobrien
158950397Sobrien    rlock_acquire();
159018334Speter    if (handle == NULL || handle == RTLD_NEXT || handle == RTLD_DEFAULT) {
159118334Speter	void *retaddr;
159218334Speter
159318334Speter	retaddr = __builtin_return_address(0);	/* __GNUC__ only */
159490075Sobrien	if ((obj = obj_from_addr(retaddr)) == NULL) {
159550397Sobrien	    _rtld_error("Cannot determine caller's shared object");
159618334Speter	    rlock_release();
159718334Speter	    return NULL;
159818334Speter	}
1599169689Skan	if (handle == NULL) {	/* Just the caller's shared object. */
160018334Speter	    def = symlook_obj(name, hash, obj, true);
160118334Speter	    defobj = obj;
1602169689Skan	} else if (handle == RTLD_NEXT) {	/* Objects after caller's */
1603169689Skan	    while ((obj = obj->next) != NULL) {
160418334Speter		if ((def = symlook_obj(name, hash, obj, true)) != NULL) {
160590075Sobrien		    defobj = obj;
160650397Sobrien		    break;
160718334Speter		}
160818334Speter	    }
160990075Sobrien	} else {
161090075Sobrien	    assert(handle == RTLD_DEFAULT);
1611169689Skan	    def = symlook_default(name, hash, obj, &defobj, true);
1612169689Skan	}
1613169689Skan    } else {
161490075Sobrien	if ((obj = dlcheck(handle)) == NULL) {
1615169689Skan	    rlock_release();
1616169689Skan	    return NULL;
1617169689Skan	}
1618169689Skan
1619169689Skan	if (obj->mainprog) {
1620169689Skan	    DoneList donelist;
1621169689Skan
1622169689Skan	    /* Search main program and all libraries loaded by it. */
1623169689Skan	    donelist_init(&donelist);
1624169689Skan	    def = symlook_list(name, hash, &list_main, &defobj, true,
1625169689Skan	      &donelist);
1626169689Skan	} else {
1627169689Skan	    /*
1628169689Skan	     * XXX - This isn't correct.  The search should include the whole
1629169689Skan	     * DAG rooted at the given object.
1630169689Skan	     */
1631169689Skan	    def = symlook_obj(name, hash, obj, true);
1632169689Skan	    defobj = obj;
1633169689Skan	}
1634169689Skan    }
1635169689Skan
1636169689Skan    if (def != NULL) {
1637169689Skan	rlock_release();
1638169689Skan	return defobj->relocbase + def->st_value;
1639169689Skan    }
1640169689Skan
1641169689Skan    _rtld_error("Undefined symbol \"%s\"", name);
1642169689Skan    rlock_release();
1643169689Skan    return NULL;
1644169689Skan}
1645169689Skan
1646169689Skanint
1647169689Skandladdr(const void *addr, Dl_info *info)
1648169689Skan{
1649169689Skan    const Obj_Entry *obj;
1650169689Skan    const Elf_Sym *def;
1651169689Skan    void *symbol_addr;
1652169689Skan    unsigned long symoffset;
1653169689Skan
1654169689Skan    rlock_acquire();
1655169689Skan    obj = obj_from_addr(addr);
1656169689Skan    if (obj == NULL) {
1657169689Skan        _rtld_error("No shared object contains address");
165890075Sobrien	rlock_release();
165990075Sobrien        return 0;
166018334Speter    }
166190075Sobrien    info->dli_fname = obj->path;
166218334Speter    info->dli_fbase = obj->mapbase;
166390075Sobrien    info->dli_saddr = (void *)0;
166418334Speter    info->dli_sname = NULL;
166518334Speter
166618334Speter    /*
166718334Speter     * Walk the symbol list looking for the symbol whose address is
166890075Sobrien     * closest to the address sent in.
166950397Sobrien     */
167090075Sobrien    for (symoffset = 0; symoffset < obj->nchains; symoffset++) {
167190075Sobrien        def = obj->symtab + symoffset;
167290075Sobrien
167318334Speter        /*
167418334Speter         * For skip the symbol if st_shndx is either SHN_UNDEF or
167518334Speter         * SHN_COMMON.
167618334Speter         */
1677169689Skan        if (def->st_shndx == SHN_UNDEF || def->st_shndx == SHN_COMMON)
1678169689Skan            continue;
1679169689Skan
1680169689Skan        /*
1681169689Skan         * If the symbol is greater than the specified address, or if it
1682169689Skan         * is further away from addr than the current nearest symbol,
168318334Speter         * then reject it.
168418334Speter         */
168518334Speter        symbol_addr = obj->relocbase + def->st_value;
168618334Speter        if (symbol_addr > addr || symbol_addr < info->dli_saddr)
1687261188Spfg            continue;
1688261188Spfg
168990075Sobrien        /* Update our idea of the nearest symbol. */
169090075Sobrien        info->dli_sname = obj->strtab + def->st_name;
1691132718Skan        info->dli_saddr = symbol_addr;
1692132718Skan
1693132718Skan        /* Exact match? */
1694132718Skan        if (info->dli_saddr == addr)
1695132718Skan            break;
1696132718Skan    }
169790075Sobrien    rlock_release();
1698132718Skan    return 1;
1699169689Skan}
170090075Sobrien
170190075Sobrienstatic void
170218334Speterlinkmap_add(Obj_Entry *obj)
170318334Speter{
170418334Speter    struct link_map *l = &obj->linkmap;
170518334Speter    struct link_map *prev;
170690075Sobrien
170790075Sobrien    obj->linkmap.l_name = obj->path;
170818334Speter    obj->linkmap.l_addr = obj->mapbase;
170918334Speter    obj->linkmap.l_ld = obj->dynamic;
171018334Speter#ifdef __mips__
171118334Speter    /* GDB needs load offset on MIPS to use the symbols */
171218334Speter    obj->linkmap.l_offs = obj->relocbase;
171318334Speter#endif
171418334Speter
171518334Speter    if (r_debug.r_map == NULL) {
171618334Speter	r_debug.r_map = l;
171718334Speter	return;
171852284Sobrien    }
171918334Speter
172050397Sobrien    /*
172150397Sobrien     * Scan to the end of the list, but not past the entry for the
172218334Speter     * dynamic linker, which we want to keep at the very end.
1723169689Skan     */
1724169689Skan    for (prev = r_debug.r_map;
1725169689Skan      prev->l_next != NULL && prev->l_next != &obj_rtld.linkmap;
1726169689Skan      prev = prev->l_next)
172718334Speter	;
172852284Sobrien
172952284Sobrien    /* Link in the new entry. */
173090075Sobrien    l->l_prev = prev;
173190075Sobrien    l->l_next = prev->l_next;
173290075Sobrien    if (l->l_next != NULL)
173390075Sobrien	l->l_next->l_prev = l;
173452284Sobrien    prev->l_next = l;
173590075Sobrien}
173690075Sobrien
173790075Sobrienstatic void
173890075Sobrienlinkmap_delete(Obj_Entry *obj)
173990075Sobrien{
174052284Sobrien    struct link_map *l = &obj->linkmap;
174152284Sobrien
174252284Sobrien    if (l->l_prev == NULL) {
174352284Sobrien	if ((r_debug.r_map = l->l_next) != NULL)
174450397Sobrien	    l->l_next->l_prev = NULL;
1745132718Skan	return;
1746132718Skan    }
1747132718Skan
1748132718Skan    if ((l->l_prev->l_next = l->l_next) != NULL)
1749169689Skan	l->l_next->l_prev = l->l_prev;
1750132718Skan}
1751132718Skan
1752132718Skan/*
1753132718Skan * Function for the debugger to set a breakpoint on to gain control.
175490075Sobrien *
1755169689Skan * The two parameters allow the debugger to easily find and determine
1756169689Skan * what the runtime loader is doing and to whom it is doing it.
175752284Sobrien *
175850397Sobrien * When the loadhook trap is hit (r_debug_state, set at program
175950397Sobrien * initialization), the arguments can be found on the stack:
176050397Sobrien *
176150397Sobrien *  +8   struct link_map *m
176252284Sobrien *  +4   struct r_debug  *rd
176352284Sobrien *  +0   RetAddr
176452284Sobrien */
176552284Sobrienvoid
176690075Sobrienr_debug_state(struct r_debug* rd, struct link_map *m)
176790075Sobrien{
176890075Sobrien}
176918334Speter
177018334Speter/*
177118334Speter * Set a pointer variable in the main program to the given value.  This
177218334Speter * is used to set key variables such as "environ" before any of the
177318334Speter * init functions are called.
177418334Speter */
177518334Speterstatic void
177618334Speterset_program_var(const char *name, const void *value)
177718334Speter{
177818334Speter    const Obj_Entry *obj;
177918334Speter    unsigned long hash;
178090075Sobrien
178118334Speter    hash = elf_hash(name);
178218334Speter    for (obj = obj_main;  obj != NULL;  obj = obj->next) {
178390075Sobrien	const Elf_Sym *def;
1784117395Skan
178590075Sobrien	if ((def = symlook_obj(name, hash, obj, false)) != NULL) {
178618334Speter	    const void **addr;
178718334Speter
178818334Speter	    addr = (const void **)(obj->relocbase + def->st_value);
178918334Speter	    dbg("\"%s\": *%p <-- %p", name, addr, value);
179018334Speter	    *addr = value;
179196263Sobrien	    break;
179296263Sobrien	}
179396263Sobrien    }
179496263Sobrien}
179596263Sobrien
179696263Sobrien/*
179796263Sobrien * Given a symbol name in a referencing object, find the corresponding
179818334Speter * definition of the symbol.  Returns a pointer to the symbol, or NULL if
179990075Sobrien * no definition was found.  Returns a pointer to the Obj_Entry of the
180090075Sobrien * defining object via the reference parameter DEFOBJ_OUT.
180190075Sobrien */
180218334Speterstatic const Elf_Sym *
180318334Spetersymlook_default(const char *name, unsigned long hash,
180418334Speter    const Obj_Entry *refobj, const Obj_Entry **defobj_out, bool in_plt)
180518334Speter{
180618334Speter    DoneList donelist;
180718334Speter    const Elf_Sym *def;
1808169689Skan    const Elf_Sym *symp;
1809169689Skan    const Obj_Entry *obj;
1810169689Skan    const Obj_Entry *defobj;
1811169689Skan    const Objlist_Entry *elm;
1812169689Skan    def = NULL;
1813169689Skan    defobj = NULL;
1814169689Skan    donelist_init(&donelist);
1815169689Skan
1816169689Skan    /* Look first in the referencing object if linked symbolically. */
1817169689Skan    if (refobj->symbolic && !donelist_check(&donelist, refobj)) {
1818169689Skan	symp = symlook_obj(name, hash, refobj, in_plt);
181918334Speter	if (symp != NULL) {
182018334Speter	    def = symp;
182118334Speter	    defobj = refobj;
182218334Speter	}
182390075Sobrien    }
182490075Sobrien
182590075Sobrien    /* Search all objects loaded at program start up. */
182690075Sobrien    if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) {
182790075Sobrien	symp = symlook_list(name, hash, &list_main, &obj, in_plt, &donelist);
182850397Sobrien	if (symp != NULL &&
182990075Sobrien	  (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
183090075Sobrien	    def = symp;
183118334Speter	    defobj = obj;
183290075Sobrien	}
183390075Sobrien    }
183490075Sobrien
183590075Sobrien    /* Search all dlopened DAGs containing the referencing object. */
183690075Sobrien    STAILQ_FOREACH(elm, &refobj->dldags, link) {
183718334Speter	if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK)
183890075Sobrien	    break;
183990075Sobrien	symp = symlook_list(name, hash, &elm->obj->dagmembers, &obj, in_plt,
184090075Sobrien	  &donelist);
184118334Speter	if (symp != NULL &&
184290075Sobrien	  (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
184390075Sobrien	    def = symp;
184418334Speter	    defobj = obj;
184590075Sobrien	}
184690075Sobrien    }
184718334Speter
184890075Sobrien    /* Search all RTLD_GLOBAL objects. */
1849117395Skan    if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) {
185090075Sobrien	symp = symlook_list(name, hash, &list_global, &obj, in_plt, &donelist);
185118334Speter	if (symp != NULL &&
185218334Speter	  (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) {
185318334Speter	    def = symp;
1854169689Skan	    defobj = obj;
185550397Sobrien	}
185650397Sobrien    }
185790075Sobrien
185890075Sobrien    /*
185990075Sobrien     * Search the dynamic linker itself, and possibly resolve the
1860117395Skan     * symbol from there.  This is how the application links to
186190075Sobrien     * dynamic linker services such as dlopen.  Only the values listed
186290075Sobrien     * in the "exports" array can be resolved from the dynamic linker.
186390075Sobrien     */
186450397Sobrien    if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) {
186590075Sobrien	symp = symlook_obj(name, hash, &obj_rtld, in_plt);
186690075Sobrien	if (symp != NULL && is_exported(symp)) {
186790075Sobrien	    def = symp;
186890075Sobrien	    defobj = &obj_rtld;
186990075Sobrien	}
187090075Sobrien    }
187190075Sobrien
187218334Speter    if (def != NULL)
187318334Speter	*defobj_out = defobj;
187418334Speter    return def;
187518334Speter}
187618334Speter
1877132718Skanstatic const Elf_Sym *
187818334Spetersymlook_list(const char *name, unsigned long hash, Objlist *objlist,
187990075Sobrien  const Obj_Entry **defobj_out, bool in_plt, DoneList *dlp)
188018334Speter{
188118334Speter    const Elf_Sym *symp;
188218334Speter    const Elf_Sym *def;
188390075Sobrien    const Obj_Entry *defobj;
188418334Speter    const Objlist_Entry *elm;
188518334Speter
188618334Speter    def = NULL;
188718334Speter    defobj = NULL;
188818334Speter    STAILQ_FOREACH(elm, objlist, link) {
188918334Speter	if (donelist_check(dlp, elm->obj))
1890132718Skan	    continue;
189118334Speter	if ((symp = symlook_obj(name, hash, elm->obj, in_plt)) != NULL) {
189290075Sobrien	    if (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK) {
189318334Speter		def = symp;
189418334Speter		defobj = elm->obj;
189518334Speter		if (ELF_ST_BIND(def->st_info) != STB_WEAK)
189618334Speter		    break;
189718334Speter	    }
189818334Speter	}
189990075Sobrien    }
190090075Sobrien    if (def != NULL)
190190075Sobrien	*defobj_out = defobj;
190218334Speter    return def;
190390075Sobrien}
1904169689Skan
190590075Sobrien/*
190690075Sobrien * Search the symbol table of a single shared object for a symbol of
1907169689Skan * the given name.  Returns a pointer to the symbol, or NULL if no
190890075Sobrien * definition was found.
190990075Sobrien *
191090075Sobrien * The symbol's hash value is passed in for efficiency reasons; that
191190075Sobrien * eliminates many recomputations of the hash value.
191290075Sobrien */
1913169689Skanconst Elf_Sym *
1914169689Skansymlook_obj(const char *name, unsigned long hash, const Obj_Entry *obj,
1915169689Skan  bool in_plt)
1916169689Skan{
191790075Sobrien    if (obj->buckets != NULL) {
1918169689Skan	unsigned long symnum = obj->buckets[hash % obj->nbuckets];
1919169689Skan
192090075Sobrien	while (symnum != STN_UNDEF) {
192190075Sobrien	    const Elf_Sym *symp;
1922169689Skan	    const char *strp;
192390075Sobrien
192490075Sobrien	    if (symnum >= obj->nchains)
1925169689Skan		return NULL;	/* Bad object */
1926169689Skan	    symp = obj->symtab + symnum;
1927169689Skan	    strp = obj->strtab + symp->st_name;
1928169689Skan
1929169689Skan	    if (strcmp(name, strp) == 0)
193050397Sobrien		return symp->st_shndx != SHN_UNDEF ||
193150397Sobrien		  (!in_plt && symp->st_value != 0 &&
1932132718Skan		  ELF_ST_TYPE(symp->st_info) == STT_FUNC) ? symp : NULL;
193350397Sobrien
193490075Sobrien	    symnum = obj->chains[symnum];
193550397Sobrien	}
193690075Sobrien    }
193790075Sobrien    return NULL;
193890075Sobrien}
1939169689Skan
1940169689Skanstatic void
194190075Sobrientrace_loaded_objects(Obj_Entry *obj)
194290075Sobrien{
194350397Sobrien    char	*fmt1, *fmt2, *fmt, *main_local;
1944169689Skan    int		c;
194550397Sobrien
1946169689Skan    if ((main_local = getenv("LD_TRACE_LOADED_OBJECTS_PROGNAME")) == NULL)
1947169689Skan	main_local = "";
1948169689Skan
1949169689Skan    if ((fmt1 = getenv("LD_TRACE_LOADED_OBJECTS_FMT1")) == NULL)
1950169689Skan	fmt1 = "\t%o => %p (%x)\n";
1951169689Skan
1952169689Skan    if ((fmt2 = getenv("LD_TRACE_LOADED_OBJECTS_FMT2")) == NULL)
1953169689Skan	fmt2 = "\t%o (%x)\n";
195490075Sobrien
1955169689Skan    for (; obj; obj = obj->next) {
1956169689Skan	Needed_Entry		*needed;
1957169689Skan	char			*name, *path;
195890075Sobrien	bool			is_lib;
1959169689Skan
1960169689Skan	for (needed = obj->needed; needed; needed = needed->next) {
1961169689Skan	    if (needed->obj != NULL) {
1962169689Skan		if (needed->obj->traced)
1963169689Skan		    continue;
1964169689Skan		needed->obj->traced = true;
1965169689Skan		path = needed->obj->path;
1966169689Skan	    } else
1967169689Skan		path = "not found";
196850397Sobrien
1969169689Skan	    name = (char *)obj->strtab + needed->name;
1970169689Skan	    is_lib = strncmp(name, "lib", 3) == 0;	/* XXX - bogus */
1971169689Skan
1972169689Skan	    fmt = is_lib ? fmt1 : fmt2;
1973169689Skan	    while ((c = *fmt++) != '\0') {
197450397Sobrien		switch (c) {
1975169689Skan		default:
1976169689Skan		    putchar(c);
1977169689Skan		    continue;
1978169689Skan		case '\\':
1979169689Skan		    switch (c = *fmt) {
198050397Sobrien		    case '\0':
198150397Sobrien			continue;
198250397Sobrien		    case 'n':
1983169689Skan			putchar('\n');
198450397Sobrien			break;
198550397Sobrien		    case 't':
198650397Sobrien			putchar('\t');
198790075Sobrien			break;
1988169689Skan		    }
1989169689Skan		    break;
1990169689Skan		case '%':
199190075Sobrien		    switch (c = *fmt) {
1992169689Skan		    case '\0':
199390075Sobrien			continue;
1994169689Skan		    case '%':
199590075Sobrien		    default:
1996169689Skan			putchar(c);
1997169689Skan			break;
1998169689Skan		    case 'A':
1999169689Skan			printf("%s", main_local);
2000169689Skan			break;
2001169689Skan		    case 'a':
2002169689Skan			printf("%s", obj_main->path);
2003169689Skan			break;
2004169689Skan		    case 'o':
200590075Sobrien			printf("%s", name);
200650397Sobrien			break;
200790075Sobrien#if 0
2008169689Skan		    case 'm':
2009169689Skan			printf("%d", sodp->sod_major);
2010132718Skan			break;
2011132718Skan		    case 'n':
2012132718Skan			printf("%d", sodp->sod_minor);
2013132718Skan			break;
2014132718Skan#endif
2015132718Skan		    case 'p':
2016132718Skan			printf("%s", path);
2017132718Skan			break;
2018132718Skan		    case 'x':
2019132718Skan			printf("%p", needed->obj ? needed->obj->mapbase : 0);
2020132718Skan			break;
2021132718Skan		    }
2022132718Skan		    break;
2023132718Skan		}
2024132718Skan		++fmt;
2025132718Skan	    }
2026169689Skan	}
2027169689Skan    }
2028169689Skan}
2029169689Skan
2030169689Skan/*
2031169689Skan * Unload a dlopened object and its dependencies from memory and from
2032169689Skan * our data structures.  It is assumed that the DAG rooted in the
2033169689Skan * object has already been unreferenced, and that the object has a
2034169689Skan * reference count of 0.
2035169689Skan */
2036132718Skanstatic void
2037132718Skanunload_object(Obj_Entry *root)
2038132718Skan{
2039169689Skan    Obj_Entry *obj;
2040169689Skan    Obj_Entry **linkp;
2041169689Skan    Objlist_Entry *elm;
2042169689Skan
2043169689Skan    assert(root->refcount == 0);
2044169689Skan
2045169689Skan    /* Remove the DAG from all objects' DAG lists. */
2046169689Skan    STAILQ_FOREACH(elm, &root->dagmembers , link)
2047169689Skan	objlist_remove(&elm->obj->dldags, root);
2048132718Skan
2049169689Skan    /* Remove the DAG from the RTLD_GLOBAL list. */
2050169689Skan    objlist_remove(&list_global, root);
2051169689Skan
2052169689Skan    /* Unmap all objects that are no longer referenced. */
2053169689Skan    linkp = &obj_list->next;
2054169689Skan    while ((obj = *linkp) != NULL) {
2055169689Skan	if (obj->refcount == 0) {
2056169689Skan	    dbg("unloading \"%s\"", obj->path);
2057132718Skan	    munmap(obj->mapbase, obj->mapsize);
2058132718Skan	    linkmap_delete(obj);
2059132718Skan	    *linkp = obj->next;
2060132718Skan	    obj_count--;
2061132718Skan	    obj_free(obj);
2062132718Skan	} else
206318334Speter	    linkp = &obj->next;
206418334Speter    }
206518334Speter    obj_tail = linkp;
206618334Speter}
206718334Speter
206818334Speterstatic void
2069132718Skanunref_dag(Obj_Entry *root)
207018334Speter{
207190075Sobrien    const Needed_Entry *needed;
207218334Speter
207390075Sobrien    if (root->refcount == 0)
207490075Sobrien	return;
207590075Sobrien    root->refcount--;
207690075Sobrien    if (root->refcount == 0)
207790075Sobrien	for (needed = root->needed;  needed != NULL;  needed = needed->next)
207890075Sobrien	    if (needed->obj != NULL)
2079169689Skan		unref_dag(needed->obj);
2080132718Skan}
208118334Speter
208218334Speter/*
208318334Speter * Non-mallocing printf, for use by malloc itself.
208418334Speter * XXX - This doesn't belong in this module.
208518334Speter */
208618334Spetervoid
208718334Speterxprintf(const char *fmt, ...)
208818334Speter{
208918334Speter    char buf[256];
209018334Speter    va_list ap;
2091132718Skan
209218334Speter    va_start(ap, fmt);
209390075Sobrien    vsprintf(buf, fmt, ap);
209418334Speter    (void)write(1, buf, strlen(buf));
209590075Sobrien    va_end(ap);
209690075Sobrien}
209790075Sobrien