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