134192Sjdp/*- 255687Sjdp * Copyright 1996, 1997, 1998, 1999, 2000 John D. Polstra. 3110804Skan * Copyright 2003 Alexander Kabaev <kan@FreeBSD.ORG>. 4234840Skib * Copyright 2009-2012 Konstantin Belousov <kib@FreeBSD.ORG>. 5234840Skib * Copyright 2012 John Marino <draco@marino.st>. 634192Sjdp * All rights reserved. 734192Sjdp * 834192Sjdp * Redistribution and use in source and binary forms, with or without 934192Sjdp * modification, are permitted provided that the following conditions 1034192Sjdp * are met: 1134192Sjdp * 1. Redistributions of source code must retain the above copyright 1234192Sjdp * notice, this list of conditions and the following disclaimer. 1334192Sjdp * 2. Redistributions in binary form must reproduce the above copyright 1434192Sjdp * notice, this list of conditions and the following disclaimer in the 1534192Sjdp * documentation and/or other materials provided with the distribution. 1634192Sjdp * 1734192Sjdp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1834192Sjdp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1934192Sjdp * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2034192Sjdp * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2134192Sjdp * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2234192Sjdp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2334192Sjdp * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2434192Sjdp * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2534192Sjdp * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2634192Sjdp * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2734192Sjdp * 2850476Speter * $FreeBSD: stable/10/libexec/rtld-elf/rtld.c 331206 2018-03-19 14:28:58Z marius $ 2934192Sjdp */ 3034192Sjdp 3134192Sjdp/* 3234192Sjdp * Dynamic linker for ELF. 3334192Sjdp * 3434192Sjdp * John Polstra <jdp@polstra.com>. 3534192Sjdp */ 3634192Sjdp 3734192Sjdp#include <sys/param.h> 38144062Scperciva#include <sys/mount.h> 3934192Sjdp#include <sys/mman.h> 4050609Sjdp#include <sys/stat.h> 41211413Skib#include <sys/sysctl.h> 42165916Sjhb#include <sys/uio.h> 43189959Skib#include <sys/utsname.h> 44165916Sjhb#include <sys/ktrace.h> 4534192Sjdp 4634192Sjdp#include <dlfcn.h> 4734192Sjdp#include <err.h> 4834192Sjdp#include <errno.h> 4934192Sjdp#include <fcntl.h> 5034192Sjdp#include <stdarg.h> 5134192Sjdp#include <stdio.h> 5234192Sjdp#include <stdlib.h> 5334192Sjdp#include <string.h> 5434192Sjdp#include <unistd.h> 5534192Sjdp 5634192Sjdp#include "debug.h" 5734192Sjdp#include "rtld.h" 58113229Smdodd#include "libmap.h" 59133063Sdfr#include "rtld_tls.h" 60225152Skib#include "rtld_printf.h" 61232831Skib#include "notes.h" 6234192Sjdp 63127250Speter#ifndef COMPAT_32BIT 64119014Sgordon#define PATH_RTLD "/libexec/ld-elf.so.1" 65127250Speter#else 66127250Speter#define PATH_RTLD "/libexec/ld-elf32.so.1" 67127250Speter#endif 6834192Sjdp 6934192Sjdp/* Types. */ 7034192Sjdptypedef void (*func_ptr_type)(); 71110804Skantypedef void * (*path_enum_proc) (const char *path, size_t len, void *arg); 7234192Sjdp 7362801Sjdp/* 7434192Sjdp * Function declarations. 7534192Sjdp */ 7645890Sjdpstatic const char *basename(const char *); 77211413Skibstatic void digest_dynamic1(Obj_Entry *, int, const Elf_Dyn **, 78238471Skib const Elf_Dyn **, const Elf_Dyn **); 79238471Skibstatic void digest_dynamic2(Obj_Entry *, const Elf_Dyn *, const Elf_Dyn *, 80238471Skib const Elf_Dyn *); 8193610Sjakestatic void digest_dynamic(Obj_Entry *, int); 8248871Sjdpstatic Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *); 8334192Sjdpstatic Obj_Entry *dlcheck(void *); 84229768Skibstatic Obj_Entry *dlopen_object(const char *name, int fd, Obj_Entry *refobj, 85234170Skib int lo_flags, int mode, RtldLockState *lockstate); 86199829Skibstatic Obj_Entry *do_load_object(int, const char *, char *, struct stat *, int); 87110804Skanstatic int do_search_info(const Obj_Entry *obj, int, struct dl_serinfo *); 8866056Sjdpstatic bool donelist_check(DoneList *, const Obj_Entry *); 8970677Sjdpstatic void errmsg_restore(char *); 9070677Sjdpstatic char *errmsg_save(void); 91110804Skanstatic void *fill_search_info(const char *, size_t, void *); 9234192Sjdpstatic char *find_library(const char *, const Obj_Entry *); 93238471Skibstatic const char *gethints(bool); 9450608Sjdpstatic void init_dag(Obj_Entry *); 95281452Skibstatic void init_pagesizes(Elf_Auxinfo **aux_info); 96211413Skibstatic void init_rtld(caddr_t, Elf_Auxinfo **); 97162449Sjkimstatic void initlist_add_neededs(Needed_Entry *, Objlist *); 98296727Skibstatic void initlist_add_objects(Obj_Entry *, Obj_Entry *, Objlist *); 9938739Sjdpstatic void linkmap_add(Obj_Entry *); 10038739Sjdpstatic void linkmap_delete(Obj_Entry *); 101216695Skibstatic void load_filtees(Obj_Entry *, int flags, RtldLockState *); 102216695Skibstatic void unload_filtees(Obj_Entry *); 103199829Skibstatic int load_needed_objects(Obj_Entry *, int); 10439551Sjdpstatic int load_preload_objects(void); 105229768Skibstatic Obj_Entry *load_object(const char *, int fd, const Obj_Entry *, int); 106217223Skibstatic void map_stacks_exec(RtldLockState *); 107312402Skibstatic int obj_enforce_relro(Obj_Entry *); 10834192Sjdpstatic Obj_Entry *obj_from_addr(const void *); 109216695Skibstatic void objlist_call_fini(Objlist *, Obj_Entry *, RtldLockState *); 110216695Skibstatic void objlist_call_init(Objlist *, RtldLockState *); 11163870Sjdpstatic void objlist_clear(Objlist *); 11250608Sjdpstatic Objlist_Entry *objlist_find(Objlist *, const Obj_Entry *); 11363870Sjdpstatic void objlist_init(Objlist *); 11463870Sjdpstatic void objlist_push_head(Objlist *, Obj_Entry *); 11563870Sjdpstatic void objlist_push_tail(Objlist *, Obj_Entry *); 116256101Skibstatic void objlist_put_after(Objlist *, Obj_Entry *, Obj_Entry *); 11750608Sjdpstatic void objlist_remove(Objlist *, Obj_Entry *); 118110804Skanstatic void *path_enumerate(const char *, path_enum_proc, void *); 119237659Skibstatic int relocate_object_dag(Obj_Entry *root, bool bind_now, 120237659Skib Obj_Entry *rtldobj, int flags, RtldLockState *lockstate); 121237659Skibstatic int relocate_object(Obj_Entry *obj, bool bind_now, Obj_Entry *rtldobj, 122237659Skib int flags, RtldLockState *lockstate); 123233231Skibstatic int relocate_objects(Obj_Entry *, bool, Obj_Entry *, int, 124233231Skib RtldLockState *); 125228503Skibstatic int resolve_objects_ifunc(Obj_Entry *first, bool bind_now, 126233231Skib int flags, RtldLockState *lockstate); 127110804Skanstatic int rtld_dirname(const char *, char *); 128189959Skibstatic int rtld_dirname_abs(const char *, char *); 129229768Skibstatic void *rtld_dlopen(const char *name, int fd, int mode); 13034192Sjdpstatic void rtld_exit(void); 13134192Sjdpstatic char *search_library_path(const char *, const char *); 132217223Skibstatic const void **get_program_var_addr(const char *, RtldLockState *); 13345890Sjdpstatic void set_program_var(const char *, const void *); 134216695Skibstatic int symlook_default(SymLook *, const Obj_Entry *refobj); 135217223Skibstatic int symlook_global(SymLook *, DoneList *); 136216695Skibstatic void symlook_init_from_req(SymLook *, const SymLook *); 137216695Skibstatic int symlook_list(SymLook *, const Objlist *, DoneList *); 138216695Skibstatic int symlook_needed(SymLook *, const Needed_Entry *, DoneList *); 139234841Skibstatic int symlook_obj1_sysv(SymLook *, const Obj_Entry *); 140234841Skibstatic int symlook_obj1_gnu(SymLook *, const Obj_Entry *); 141162449Sjkimstatic void trace_loaded_objects(Obj_Entry *); 142111054Skanstatic void unlink_object(Obj_Entry *); 14355687Sjdpstatic void unload_object(Obj_Entry *); 14450608Sjdpstatic void unref_dag(Obj_Entry *); 145114826Skanstatic void ref_dag(Obj_Entry *); 146282412Skibstatic char *origin_subst_one(Obj_Entry *, char *, const char *, 147282412Skib const char *, bool); 148282412Skibstatic char *origin_subst(Obj_Entry *, char *); 149282412Skibstatic bool obj_resolve_origin(Obj_Entry *obj); 150232831Skibstatic void preinit_main(void); 151153515Skanstatic int rtld_verify_versions(const Objlist *); 152153515Skanstatic int rtld_verify_object_versions(Obj_Entry *); 153153515Skanstatic void object_add_name(Obj_Entry *, const char *); 154153515Skanstatic int object_match_name(const Obj_Entry *, const char *); 155165916Sjhbstatic void ld_utrace_log(int, void *, void *, size_t, int, const char *); 156211705Skibstatic void rtld_fill_dl_phdr_info(const Obj_Entry *obj, 157211705Skib struct dl_phdr_info *phdr_info); 158234841Skibstatic uint32_t gnu_hash(const char *); 159234840Skibstatic bool matched_symbol(SymLook *, const Obj_Entry *, Sym_Match_Result *, 160234840Skib const unsigned long); 16134192Sjdp 162281453Skibvoid r_debug_state(struct r_debug *, struct link_map *) __noinline __exported; 163281453Skibvoid _r_debug_postinit(struct link_map *) __noinline __exported; 16434192Sjdp 16534192Sjdp/* 16634192Sjdp * Data declarations. 16734192Sjdp */ 16834192Sjdpstatic char *error_message; /* Message for dlerror(), or NULL */ 169281453Skibstruct r_debug r_debug __exported; /* for GDB; */ 170115444Smdoddstatic bool libmap_disable; /* Disable libmap */ 171216695Skibstatic bool ld_loadfltr; /* Immediate filters processing */ 172141232Smdoddstatic char *libmap_override; /* Maps to use in addition to libmap.conf */ 17334192Sjdpstatic bool trust; /* False for setuid and setgid programs */ 174144062Scpercivastatic bool dangerous_ld_env; /* True if environment variables have been 175144062Scperciva used to affect the libraries loaded */ 17634192Sjdpstatic char *ld_bind_now; /* Environment variable for immediate binding */ 17734192Sjdpstatic char *ld_debug; /* Environment variable for debugging */ 17834192Sjdpstatic char *ld_library_path; /* Environment variable for search path */ 17939551Sjdpstatic char *ld_preload; /* Environment variable for libraries to 18039551Sjdp load first */ 181190324Sdelphijstatic char *ld_elf_hints_path; /* Environment variable for alternative hints path */ 18235574Sdfrstatic char *ld_tracing; /* Called from ldd to print libs */ 183165916Sjhbstatic char *ld_utrace; /* Use utrace() to log events. */ 184296727Skibstatic struct obj_entry_q obj_list; /* Queue of all loaded objects */ 18534192Sjdpstatic Obj_Entry *obj_main; /* The main program shared object */ 18634192Sjdpstatic Obj_Entry obj_rtld; /* The dynamic linker shared object */ 18762801Sjdpstatic unsigned int obj_count; /* Number of objects in obj_list */ 188296727Skibstatic unsigned int obj_loads; /* Number of loads of objects (gen count) */ 18934192Sjdp 19050608Sjdpstatic Objlist list_global = /* Objects dlopened with RTLD_GLOBAL */ 19150608Sjdp STAILQ_HEAD_INITIALIZER(list_global); 19250608Sjdpstatic Objlist list_main = /* Objects loaded at program startup */ 19350608Sjdp STAILQ_HEAD_INITIALIZER(list_main); 19463870Sjdpstatic Objlist list_fini = /* Objects needing fini() calls */ 19563870Sjdp STAILQ_HEAD_INITIALIZER(list_fini); 19650608Sjdp 197212497SnwhitehornElf_Sym sym_zero; /* For resolving undefined weak refs. */ 19845320Sjdp 19965109Sjwd#define GDB_STATE(s,m) r_debug.r_state = s; r_debug_state(&r_debug,m); 20035529Sdfr 20138816Sdfrextern Elf_Dyn _DYNAMIC; 20245501Sjdp#pragma weak _DYNAMIC 203130661Stmm#ifndef RTLD_IS_DYNAMIC 204130661Stmm#define RTLD_IS_DYNAMIC() (&_DYNAMIC != NULL) 205130661Stmm#endif 20638816Sdfr 207281453Skibint dlclose(void *) __exported; 208281453Skibchar *dlerror(void) __exported; 209281453Skibvoid *dlopen(const char *, int) __exported; 210281453Skibvoid *fdlopen(int, int) __exported; 211281453Skibvoid *dlsym(void *, const char *) __exported; 212281453Skibdlfunc_t dlfunc(void *, const char *) __exported; 213281453Skibvoid *dlvsym(void *, const char *, const char *) __exported; 214281453Skibint dladdr(const void *, Dl_info *) __exported; 215281453Skibvoid dllockinit(void *, void *(*)(void *), void (*)(void *), void (*)(void *), 216281453Skib void (*)(void *), void (*)(void *), void (*)(void *)) __exported; 217281453Skibint dlinfo(void *, int , void *) __exported; 218281453Skibint dl_iterate_phdr(__dl_iterate_hdr_callback, void *) __exported; 219281453Skibint _rtld_addr_phdr(const void *, struct dl_phdr_info *) __exported; 220281453Skibint _rtld_get_stack_prot(void) __exported; 221281453Skibint _rtld_is_dlopened(void *) __exported; 222281453Skibvoid _rtld_error(const char *, ...) __exported; 223281453Skib 224281452Skibint npagesizes, osreldate; 225281452Skibsize_t *pagesizes; 226211413Skib 227232861Skiblong __stack_chk_guard[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 228232861Skib 229217851Skibstatic int stack_prot = PROT_READ | PROT_WRITE | RTLD_DEFAULT_STACK_EXEC; 230217153Skibstatic int max_stack_flags; 231217153Skib 23234192Sjdp/* 23334192Sjdp * Global declarations normally provided by crt1. The dynamic linker is 23455687Sjdp * not built with crt1, so we have to provide them ourselves. 23534192Sjdp */ 23634192Sjdpchar *__progname; 23734192Sjdpchar **environ; 23834192Sjdp 23962801Sjdp/* 240232831Skib * Used to pass argc, argv to init functions. 241232831Skib */ 242232831Skibint main_argc; 243232831Skibchar **main_argv; 244232831Skib 245232831Skib/* 246133063Sdfr * Globals to control TLS allocation. 247133063Sdfr */ 248133063Sdfrsize_t tls_last_offset; /* Static TLS offset of last module */ 249133063Sdfrsize_t tls_last_size; /* Static TLS size of last module */ 250133063Sdfrsize_t tls_static_space; /* Static TLS space allocated */ 251259292Skibsize_t tls_static_max_align; 252133063Sdfrint tls_dtv_generation = 1; /* Used to detect when dtv size changes */ 253133063Sdfrint tls_max_index = 1; /* Largest module index allocated */ 254133063Sdfr 255238471Skibbool ld_library_path_rpath = false; 256238471Skib 257133063Sdfr/* 25862801Sjdp * Fill in a DoneList with an allocation large enough to hold all of 25962801Sjdp * the currently-loaded objects. Keep this as a macro since it calls 26062801Sjdp * alloca and we want that to occur within the scope of the caller. 26162801Sjdp */ 26262801Sjdp#define donelist_init(dlp) \ 26362801Sjdp ((dlp)->objs = alloca(obj_count * sizeof (dlp)->objs[0]), \ 26462801Sjdp assert((dlp)->objs != NULL), \ 26562801Sjdp (dlp)->num_alloc = obj_count, \ 26662801Sjdp (dlp)->num_used = 0) 26762801Sjdp 268165916Sjhb#define UTRACE_DLOPEN_START 1 269165916Sjhb#define UTRACE_DLOPEN_STOP 2 270165916Sjhb#define UTRACE_DLCLOSE_START 3 271165916Sjhb#define UTRACE_DLCLOSE_STOP 4 272165916Sjhb#define UTRACE_LOAD_OBJECT 5 273165916Sjhb#define UTRACE_UNLOAD_OBJECT 6 274165916Sjhb#define UTRACE_ADD_RUNDEP 7 275165916Sjhb#define UTRACE_PRELOAD_FINISHED 8 276165916Sjhb#define UTRACE_INIT_CALL 9 277165916Sjhb#define UTRACE_FINI_CALL 10 278284954Sdes#define UTRACE_DLSYM_START 11 279284954Sdes#define UTRACE_DLSYM_STOP 12 280165916Sjhb 281165916Sjhbstruct utrace_rtld { 282165916Sjhb char sig[4]; /* 'RTLD' */ 283165916Sjhb int event; 284165916Sjhb void *handle; 285165916Sjhb void *mapbase; /* Used for 'parent' and 'init/fini' */ 286165916Sjhb size_t mapsize; 287165916Sjhb int refcnt; /* Used for 'mode' */ 288165916Sjhb char name[MAXPATHLEN]; 289165916Sjhb}; 290165916Sjhb 291165916Sjhb#define LD_UTRACE(e, h, mb, ms, r, n) do { \ 292165916Sjhb if (ld_utrace != NULL) \ 293165916Sjhb ld_utrace_log(e, h, mb, ms, r, n); \ 294165916Sjhb} while (0) 295165916Sjhb 296165916Sjhbstatic void 297165916Sjhbld_utrace_log(int event, void *handle, void *mapbase, size_t mapsize, 298165916Sjhb int refcnt, const char *name) 299165916Sjhb{ 300165916Sjhb struct utrace_rtld ut; 301165916Sjhb 302165916Sjhb ut.sig[0] = 'R'; 303165916Sjhb ut.sig[1] = 'T'; 304165916Sjhb ut.sig[2] = 'L'; 305165916Sjhb ut.sig[3] = 'D'; 306165916Sjhb ut.event = event; 307165916Sjhb ut.handle = handle; 308165916Sjhb ut.mapbase = mapbase; 309165916Sjhb ut.mapsize = mapsize; 310165916Sjhb ut.refcnt = refcnt; 311165916Sjhb bzero(ut.name, sizeof(ut.name)); 312165916Sjhb if (name) 313165916Sjhb strlcpy(ut.name, name, sizeof(ut.name)); 314165916Sjhb utrace(&ut, sizeof(ut)); 315165916Sjhb} 316165916Sjhb 31734192Sjdp/* 31834192Sjdp * Main entry point for dynamic linking. The first argument is the 31934192Sjdp * stack pointer. The stack is expected to be laid out as described 32034192Sjdp * in the SVR4 ABI specification, Intel 386 Processor Supplement. 32134192Sjdp * Specifically, the stack pointer points to a word containing 32234192Sjdp * ARGC. Following that in the stack is a null-terminated sequence 32334192Sjdp * of pointers to argument strings. Then comes a null-terminated 32434192Sjdp * sequence of pointers to environment strings. Finally, there is a 32534192Sjdp * sequence of "auxiliary vector" entries. 32634192Sjdp * 32734192Sjdp * The second argument points to a place to store the dynamic linker's 32838816Sdfr * exit procedure pointer and the third to a place to store the main 32938816Sdfr * program's object. 33034192Sjdp * 33134192Sjdp * The return value is the main program's entry point. 33234192Sjdp */ 33334192Sjdpfunc_ptr_type 33438816Sdfr_rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) 33534192Sjdp{ 33638816Sdfr Elf_Auxinfo *aux_info[AT_COUNT]; 33734192Sjdp int i; 33834192Sjdp int argc; 33934192Sjdp char **argv; 34034192Sjdp char **env; 34138816Sdfr Elf_Auxinfo *aux; 34238816Sdfr Elf_Auxinfo *auxp; 34348871Sjdp const char *argv0; 344133063Sdfr Objlist_Entry *entry; 34550608Sjdp Obj_Entry *obj; 346296727Skib Obj_Entry *preload_tail; 347256101Skib Obj_Entry *last_interposer; 34863870Sjdp Objlist initlist; 349216695Skib RtldLockState lockstate; 350238471Skib char *library_path_rpath; 351232861Skib int mib[2]; 352232861Skib size_t len; 35334192Sjdp 35434192Sjdp /* 35534192Sjdp * On entry, the dynamic linker itself has not been relocated yet. 35634192Sjdp * Be very careful not to reference any global data until after 35734192Sjdp * init_rtld has returned. It is OK to reference file-scope statics 35834192Sjdp * and string constants, and to call static and global functions. 35934192Sjdp */ 36034192Sjdp 36134192Sjdp /* Find the auxiliary vector on the stack. */ 36234192Sjdp argc = *sp++; 36334192Sjdp argv = (char **) sp; 36434192Sjdp sp += argc + 1; /* Skip over arguments and NULL terminator */ 36534192Sjdp env = (char **) sp; 36634192Sjdp while (*sp++ != 0) /* Skip over environment, and NULL terminator */ 36734192Sjdp ; 36838816Sdfr aux = (Elf_Auxinfo *) sp; 36934192Sjdp 37034192Sjdp /* Digest the auxiliary vector. */ 37134192Sjdp for (i = 0; i < AT_COUNT; i++) 37234192Sjdp aux_info[i] = NULL; 37334192Sjdp for (auxp = aux; auxp->a_type != AT_NULL; auxp++) { 37434192Sjdp if (auxp->a_type < AT_COUNT) 37534192Sjdp aux_info[auxp->a_type] = auxp; 37634192Sjdp } 37734192Sjdp 37834192Sjdp /* Initialize and relocate ourselves. */ 37934192Sjdp assert(aux_info[AT_BASE] != NULL); 380211413Skib init_rtld((caddr_t) aux_info[AT_BASE]->a_un.a_ptr, aux_info); 38134192Sjdp 38234192Sjdp __progname = obj_rtld.path; 38348871Sjdp argv0 = argv[0] != NULL ? argv[0] : "(null)"; 38434192Sjdp environ = env; 385232831Skib main_argc = argc; 386232831Skib main_argv = argv; 38734192Sjdp 388233927Skib if (aux_info[AT_CANARY] != NULL && 389233927Skib aux_info[AT_CANARY]->a_un.a_ptr != NULL) { 390232861Skib i = aux_info[AT_CANARYLEN]->a_un.a_val; 391232861Skib if (i > sizeof(__stack_chk_guard)) 392232861Skib i = sizeof(__stack_chk_guard); 393232861Skib memcpy(__stack_chk_guard, aux_info[AT_CANARY]->a_un.a_ptr, i); 394232861Skib } else { 395232861Skib mib[0] = CTL_KERN; 396232861Skib mib[1] = KERN_ARND; 397232861Skib 398232861Skib len = sizeof(__stack_chk_guard); 399232861Skib if (sysctl(mib, 2, __stack_chk_guard, &len, NULL, 0) == -1 || 400232861Skib len != sizeof(__stack_chk_guard)) { 401232861Skib /* If sysctl was unsuccessful, use the "terminator canary". */ 402232861Skib ((unsigned char *)(void *)__stack_chk_guard)[0] = 0; 403232861Skib ((unsigned char *)(void *)__stack_chk_guard)[1] = 0; 404232861Skib ((unsigned char *)(void *)__stack_chk_guard)[2] = '\n'; 405232861Skib ((unsigned char *)(void *)__stack_chk_guard)[3] = 255; 406232861Skib } 407232861Skib } 408232861Skib 409115448Smdodd trust = !issetugid(); 41034192Sjdp 411127250Speter ld_bind_now = getenv(LD_ "BIND_NOW"); 412169661Scsjp /* 413169661Scsjp * If the process is tainted, then we un-set the dangerous environment 414169661Scsjp * variables. The process will be marked as tainted until setuid(2) 415169661Scsjp * is called. If any child process calls setuid(2) we do not want any 416169661Scsjp * future processes to honor the potentially un-safe variables. 417169661Scsjp */ 418169661Scsjp if (!trust) { 419199979Scperciva if (unsetenv(LD_ "PRELOAD") || unsetenv(LD_ "LIBMAP") || 420199979Scperciva unsetenv(LD_ "LIBRARY_PATH") || unsetenv(LD_ "LIBMAP_DISABLE") || 421216695Skib unsetenv(LD_ "DEBUG") || unsetenv(LD_ "ELF_HINTS_PATH") || 422238471Skib unsetenv(LD_ "LOADFLTR") || unsetenv(LD_ "LIBRARY_PATH_RPATH")) { 423199979Scperciva _rtld_error("environment corrupt; aborting"); 424282118Semaste rtld_die(); 425199979Scperciva } 426169661Scsjp } 427169661Scsjp ld_debug = getenv(LD_ "DEBUG"); 428169661Scsjp libmap_disable = getenv(LD_ "LIBMAP_DISABLE") != NULL; 429169661Scsjp libmap_override = getenv(LD_ "LIBMAP"); 430169661Scsjp ld_library_path = getenv(LD_ "LIBRARY_PATH"); 431169661Scsjp ld_preload = getenv(LD_ "PRELOAD"); 432190324Sdelphij ld_elf_hints_path = getenv(LD_ "ELF_HINTS_PATH"); 433216695Skib ld_loadfltr = getenv(LD_ "LOADFLTR") != NULL; 434238471Skib library_path_rpath = getenv(LD_ "LIBRARY_PATH_RPATH"); 435238471Skib if (library_path_rpath != NULL) { 436238471Skib if (library_path_rpath[0] == 'y' || 437238471Skib library_path_rpath[0] == 'Y' || 438238471Skib library_path_rpath[0] == '1') 439238471Skib ld_library_path_rpath = true; 440238471Skib else 441238471Skib ld_library_path_rpath = false; 442238471Skib } 443169661Scsjp dangerous_ld_env = libmap_disable || (libmap_override != NULL) || 444190324Sdelphij (ld_library_path != NULL) || (ld_preload != NULL) || 445216695Skib (ld_elf_hints_path != NULL) || ld_loadfltr; 446127250Speter ld_tracing = getenv(LD_ "TRACE_LOADED_OBJECTS"); 447165916Sjhb ld_utrace = getenv(LD_ "UTRACE"); 44834192Sjdp 449190324Sdelphij if ((ld_elf_hints_path == NULL) || strlen(ld_elf_hints_path) == 0) 450190324Sdelphij ld_elf_hints_path = _PATH_ELF_HINTS; 451190324Sdelphij 45234192Sjdp if (ld_debug != NULL && *ld_debug != '\0') 45334192Sjdp debug = 1; 45434192Sjdp dbg("%s is initialized, base address = %p", __progname, 45534192Sjdp (caddr_t) aux_info[AT_BASE]->a_un.a_ptr); 45645501Sjdp dbg("RTLD dynamic = %p", obj_rtld.dynamic); 45745501Sjdp dbg("RTLD pltgot = %p", obj_rtld.pltgot); 45834192Sjdp 459216695Skib dbg("initializing thread locks"); 460216695Skib lockdflt_init(); 461216695Skib 46234192Sjdp /* 46334192Sjdp * Load the main program, or process its program header if it is 46434192Sjdp * already loaded. 46534192Sjdp */ 46634192Sjdp if (aux_info[AT_EXECFD] != NULL) { /* Load the main program. */ 46734192Sjdp int fd = aux_info[AT_EXECFD]->a_un.a_val; 46834192Sjdp dbg("loading main program"); 46950609Sjdp obj_main = map_object(fd, argv0, NULL); 47034192Sjdp close(fd); 47134192Sjdp if (obj_main == NULL) 472282118Semaste rtld_die(); 473323877Sjhb max_stack_flags = obj_main->stack_flags; 47434192Sjdp } else { /* Main program already loaded. */ 47538816Sdfr const Elf_Phdr *phdr; 47634192Sjdp int phnum; 47734192Sjdp caddr_t entry; 47834192Sjdp 47934192Sjdp dbg("processing main program's program header"); 48034192Sjdp assert(aux_info[AT_PHDR] != NULL); 48138816Sdfr phdr = (const Elf_Phdr *) aux_info[AT_PHDR]->a_un.a_ptr; 48234192Sjdp assert(aux_info[AT_PHNUM] != NULL); 48334192Sjdp phnum = aux_info[AT_PHNUM]->a_un.a_val; 48434192Sjdp assert(aux_info[AT_PHENT] != NULL); 48538816Sdfr assert(aux_info[AT_PHENT]->a_un.a_val == sizeof(Elf_Phdr)); 48634192Sjdp assert(aux_info[AT_ENTRY] != NULL); 48734192Sjdp entry = (caddr_t) aux_info[AT_ENTRY]->a_un.a_ptr; 48848871Sjdp if ((obj_main = digest_phdr(phdr, phnum, entry, argv0)) == NULL) 489282118Semaste rtld_die(); 49034192Sjdp } 49134192Sjdp 492189959Skib if (aux_info[AT_EXECPATH] != 0) { 493189959Skib char *kexecpath; 494189959Skib char buf[MAXPATHLEN]; 495189959Skib 496189959Skib kexecpath = aux_info[AT_EXECPATH]->a_un.a_ptr; 497189959Skib dbg("AT_EXECPATH %p %s", kexecpath, kexecpath); 498189959Skib if (kexecpath[0] == '/') 499189959Skib obj_main->path = kexecpath; 500189959Skib else if (getcwd(buf, sizeof(buf)) == NULL || 501189959Skib strlcat(buf, "/", sizeof(buf)) >= sizeof(buf) || 502189959Skib strlcat(buf, kexecpath, sizeof(buf)) >= sizeof(buf)) 503189959Skib obj_main->path = xstrdup(argv0); 504189959Skib else 505189959Skib obj_main->path = xstrdup(buf); 506189959Skib } else { 507189959Skib dbg("No AT_EXECPATH"); 508189959Skib obj_main->path = xstrdup(argv0); 509189959Skib } 510189959Skib dbg("obj_main path %s", obj_main->path); 51134192Sjdp obj_main->mainprog = true; 51250610Sjdp 513217153Skib if (aux_info[AT_STACKPROT] != NULL && 514217153Skib aux_info[AT_STACKPROT]->a_un.a_val != 0) 515217153Skib stack_prot = aux_info[AT_STACKPROT]->a_un.a_val; 516217153Skib 517279218Sjhb#ifndef COMPAT_32BIT 51850610Sjdp /* 51950610Sjdp * Get the actual dynamic linker pathname from the executable if 52050610Sjdp * possible. (It should always be possible.) That ensures that 52150610Sjdp * gdb will find the right dynamic linker even if a non-standard 52250610Sjdp * one is being used. 52350610Sjdp */ 52450610Sjdp if (obj_main->interp != NULL && 52550610Sjdp strcmp(obj_main->interp, obj_rtld.path) != 0) { 52650610Sjdp free(obj_rtld.path); 52750610Sjdp obj_rtld.path = xstrdup(obj_main->interp); 528127579Sdfr __progname = obj_rtld.path; 52950610Sjdp } 530279218Sjhb#endif 53150610Sjdp 53293610Sjake digest_dynamic(obj_main, 0); 533234841Skib dbg("%s valid_hash_sysv %d valid_hash_gnu %d dynsymcount %d", 534234841Skib obj_main->path, obj_main->valid_hash_sysv, obj_main->valid_hash_gnu, 535234841Skib obj_main->dynsymcount); 53634192Sjdp 53735529Sdfr linkmap_add(obj_main); 53835529Sdfr linkmap_add(&obj_rtld); 53935529Sdfr 54034192Sjdp /* Link the main program into the list of objects. */ 541296727Skib TAILQ_INSERT_HEAD(&obj_list, obj_main, next); 54262801Sjdp obj_count++; 543168312Skan obj_loads++; 54434192Sjdp 54545320Sjdp /* Initialize a fake symbol for resolving undefined weak references. */ 54645320Sjdp sym_zero.st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE); 54795544Smarcel sym_zero.st_shndx = SHN_UNDEF; 548197931Skib sym_zero.st_value = -(uintptr_t)obj_main->relocbase; 54945320Sjdp 550115444Smdodd if (!libmap_disable) 551141232Smdodd libmap_disable = (bool)lm_init(libmap_override); 552113229Smdodd 55339551Sjdp dbg("loading LD_PRELOAD libraries"); 55439551Sjdp if (load_preload_objects() == -1) 555282118Semaste rtld_die(); 556296727Skib preload_tail = globallist_curr(TAILQ_LAST(&obj_list, obj_entry_q)); 55739551Sjdp 55834192Sjdp dbg("loading needed objects"); 559199829Skib if (load_needed_objects(obj_main, 0) == -1) 560282118Semaste rtld_die(); 56134192Sjdp 56263870Sjdp /* Make a list of all objects loaded at startup. */ 563256101Skib last_interposer = obj_main; 564296727Skib TAILQ_FOREACH(obj, &obj_list, next) { 565296727Skib if (obj->marker) 566296727Skib continue; 567256101Skib if (obj->z_interpose && obj != obj_main) { 568256101Skib objlist_put_after(&list_main, last_interposer, obj); 569256101Skib last_interposer = obj; 570256101Skib } else { 571256101Skib objlist_push_tail(&list_main, obj); 572256101Skib } 573114826Skan obj->refcount++; 574114826Skan } 57550608Sjdp 576153515Skan dbg("checking for required versions"); 577153515Skan if (rtld_verify_versions(&list_main) == -1 && !ld_tracing) 578282118Semaste rtld_die(); 579153515Skan 58035574Sdfr if (ld_tracing) { /* We're done */ 58135574Sdfr trace_loaded_objects(obj_main); 58235574Sdfr exit(0); 58335574Sdfr } 58435574Sdfr 585127250Speter if (getenv(LD_ "DUMP_REL_PRE") != NULL) { 586116563Smdodd dump_relocations(obj_main); 587116563Smdodd exit (0); 588116563Smdodd } 589116563Smdodd 590226155Skib /* 591226155Skib * Processing tls relocations requires having the tls offsets 592226155Skib * initialized. Prepare offsets before starting initial 593226155Skib * relocation processing. 594226155Skib */ 595226155Skib dbg("initializing initial thread local storage offsets"); 596137121Sssouhlal STAILQ_FOREACH(entry, &list_main, link) { 597137121Sssouhlal /* 598137121Sssouhlal * Allocate all the initial objects out of the static TLS 599137121Sssouhlal * block even if they didn't ask for it. 600137121Sssouhlal */ 601137121Sssouhlal allocate_tls_offset(entry->obj); 602137121Sssouhlal } 603137121Sssouhlal 60434192Sjdp if (relocate_objects(obj_main, 605233231Skib ld_bind_now != NULL && *ld_bind_now != '\0', 606233231Skib &obj_rtld, SYMLOOK_EARLY, NULL) == -1) 607282118Semaste rtld_die(); 60834192Sjdp 60934192Sjdp dbg("doing copy relocations"); 61034192Sjdp if (do_copy_relocations(obj_main) == -1) 611282118Semaste rtld_die(); 61234192Sjdp 613312402Skib dbg("enforcing main obj relro"); 614312402Skib if (obj_enforce_relro(obj_main) == -1) 615312402Skib rtld_die(); 616312402Skib 617127250Speter if (getenv(LD_ "DUMP_REL_POST") != NULL) { 618116563Smdodd dump_relocations(obj_main); 619116563Smdodd exit (0); 620116563Smdodd } 621116563Smdodd 622226155Skib /* 623226155Skib * Setup TLS for main thread. This must be done after the 624226155Skib * relocations are processed, since tls initialization section 625226155Skib * might be the subject for relocations. 626226155Skib */ 627226155Skib dbg("initializing initial thread local storage"); 628296727Skib allocate_initial_tls(globallist_curr(TAILQ_FIRST(&obj_list))); 629226155Skib 63045890Sjdp dbg("initializing key program variables"); 63145890Sjdp set_program_var("__progname", argv[0] != NULL ? basename(argv[0]) : ""); 63245890Sjdp set_program_var("environ", env); 633211414Skib set_program_var("__elf_aux_vector", aux); 63445890Sjdp 63563870Sjdp /* Make a list of init functions to call. */ 63663870Sjdp objlist_init(&initlist); 637296727Skib initlist_add_objects(globallist_curr(TAILQ_FIRST(&obj_list)), 638296727Skib preload_tail, &initlist); 63963870Sjdp 64065109Sjwd r_debug_state(NULL, &obj_main->linkmap); /* say hello to gdb! */ 64148543Sjdp 642217223Skib map_stacks_exec(NULL); 643309061Skib ifunc_init(aux); 644217153Skib 645229508Skib dbg("resolving ifuncs"); 646229508Skib if (resolve_objects_ifunc(obj_main, 647233231Skib ld_bind_now != NULL && *ld_bind_now != '\0', SYMLOOK_EARLY, 648233231Skib NULL) == -1) 649282118Semaste rtld_die(); 650229508Skib 651232831Skib if (!obj_main->crt_no_init) { 652232831Skib /* 653232831Skib * Make sure we don't call the main program's init and fini 654232831Skib * functions for binaries linked with old crt1 which calls 655232831Skib * _init itself. 656232831Skib */ 657232831Skib obj_main->init = obj_main->fini = (Elf_Addr)NULL; 658232831Skib obj_main->preinit_array = obj_main->init_array = 659232831Skib obj_main->fini_array = (Elf_Addr)NULL; 660232831Skib } 661232831Skib 662331206Smarius /* 663331206Smarius * Execute MD initializers required before we call the objects' 664331206Smarius * init functions. 665331206Smarius */ 666331206Smarius pre_init(); 667331206Smarius 668216695Skib wlock_acquire(rtld_bind_lock, &lockstate); 669232831Skib if (obj_main->crt_no_init) 670232831Skib preinit_main(); 671182698Skan objlist_call_init(&initlist, &lockstate); 672269680Smarkj _r_debug_postinit(&obj_main->linkmap); 67363870Sjdp objlist_clear(&initlist); 674216695Skib dbg("loading filtees"); 675296727Skib TAILQ_FOREACH(obj, &obj_list, next) { 676296727Skib if (obj->marker) 677296727Skib continue; 678216695Skib if (ld_loadfltr || obj->z_loadfltr) 679216695Skib load_filtees(obj, 0, &lockstate); 680216695Skib } 681216695Skib lock_release(rtld_bind_lock, &lockstate); 68234192Sjdp 68334192Sjdp dbg("transferring control to program entry point = %p", obj_main->entry); 68434192Sjdp 68534192Sjdp /* Return the exit procedure and the program entry point. */ 68638816Sdfr *exit_proc = rtld_exit; 68738816Sdfr *objp = obj_main; 68834192Sjdp return (func_ptr_type) obj_main->entry; 68934192Sjdp} 69034192Sjdp 691228435Skibvoid * 692228435Skibrtld_resolve_ifunc(const Obj_Entry *obj, const Elf_Sym *def) 693228435Skib{ 694228435Skib void *ptr; 695228435Skib Elf_Addr target; 696228435Skib 697228435Skib ptr = (void *)make_function_pointer(def, obj); 698309061Skib target = call_ifunc_resolver(ptr); 699228435Skib return ((void *)target); 700228435Skib} 701228435Skib 70248205SjdpElf_Addr 703153504Smarcel_rtld_bind(Obj_Entry *obj, Elf_Size reloff) 70434192Sjdp{ 70538816Sdfr const Elf_Rel *rel; 70638816Sdfr const Elf_Sym *def; 70734192Sjdp const Obj_Entry *defobj; 70838816Sdfr Elf_Addr *where; 70948205Sjdp Elf_Addr target; 710216695Skib RtldLockState lockstate; 71134192Sjdp 712216695Skib rlock_acquire(rtld_bind_lock, &lockstate); 713218476Skib if (sigsetjmp(lockstate.env, 0) != 0) 714216695Skib lock_upgrade(rtld_bind_lock, &lockstate); 71538816Sdfr if (obj->pltrel) 71638816Sdfr rel = (const Elf_Rel *) ((caddr_t) obj->pltrel + reloff); 71738816Sdfr else 71838816Sdfr rel = (const Elf_Rel *) ((caddr_t) obj->pltrela + reloff); 71934192Sjdp 72038816Sdfr where = (Elf_Addr *) (obj->relocbase + rel->r_offset); 721309371Sjhb def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, SYMLOOK_IN_PLT, 722309371Sjhb NULL, &lockstate); 72334192Sjdp if (def == NULL) 724282118Semaste rtld_die(); 725228435Skib if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) 726228435Skib target = (Elf_Addr)rtld_resolve_ifunc(defobj, def); 727228435Skib else 728228435Skib target = (Elf_Addr)(defobj->relocbase + def->st_value); 72934192Sjdp 73034192Sjdp dbg("\"%s\" in \"%s\" ==> %p in \"%s\"", 73134192Sjdp defobj->strtab + def->st_name, basename(obj->path), 73248205Sjdp (void *)target, basename(defobj->path)); 73334192Sjdp 73485004Sdfr /* 73585004Sdfr * Write the new contents for the jmpslot. Note that depending on 73685004Sdfr * architecture, the value which we need to return back to the 73785004Sdfr * lazy binding trampoline may or may not be the target 73885004Sdfr * address. The value returned from reloc_jmpslot() is the value 73985004Sdfr * that the trampoline needs. 74085004Sdfr */ 741107071Stmm target = reloc_jmpslot(where, target, defobj, obj, rel); 742216695Skib lock_release(rtld_bind_lock, &lockstate); 74334192Sjdp return target; 74434192Sjdp} 74534192Sjdp 74634192Sjdp/* 74734192Sjdp * Error reporting function. Use it like printf. If formats the message 74834192Sjdp * into a buffer, and sets things up so that the next call to dlerror() 74934192Sjdp * will return the message. 75034192Sjdp */ 75134192Sjdpvoid 75234192Sjdp_rtld_error(const char *fmt, ...) 75334192Sjdp{ 75434192Sjdp static char buf[512]; 75534192Sjdp va_list ap; 75634192Sjdp 75734192Sjdp va_start(ap, fmt); 758225152Skib rtld_vsnprintf(buf, sizeof buf, fmt, ap); 75934192Sjdp error_message = buf; 76034192Sjdp va_end(ap); 76134192Sjdp} 76234192Sjdp 76370677Sjdp/* 76470677Sjdp * Return a dynamically-allocated copy of the current error message, if any. 76570677Sjdp */ 76670677Sjdpstatic char * 76770677Sjdperrmsg_save(void) 76870677Sjdp{ 76970677Sjdp return error_message == NULL ? NULL : xstrdup(error_message); 77070677Sjdp} 77170677Sjdp 77270677Sjdp/* 77370677Sjdp * Restore the current error message from a copy which was previously saved 77470677Sjdp * by errmsg_save(). The copy is freed. 77570677Sjdp */ 77670677Sjdpstatic void 77770677Sjdperrmsg_restore(char *saved_msg) 77870677Sjdp{ 77970677Sjdp if (saved_msg == NULL) 78070677Sjdp error_message = NULL; 78170677Sjdp else { 78270677Sjdp _rtld_error("%s", saved_msg); 78370677Sjdp free(saved_msg); 78470677Sjdp } 78570677Sjdp} 78670677Sjdp 78734192Sjdpstatic const char * 78834192Sjdpbasename(const char *name) 78934192Sjdp{ 79034192Sjdp const char *p = strrchr(name, '/'); 79134192Sjdp return p != NULL ? p + 1 : name; 79234192Sjdp} 79334192Sjdp 794189959Skibstatic struct utsname uts; 795189959Skib 796249525Skibstatic char * 797282412Skiborigin_subst_one(Obj_Entry *obj, char *real, const char *kw, 798282412Skib const char *subst, bool may_free) 799189959Skib{ 800249525Skib char *p, *p1, *res, *resp; 801249525Skib int subst_len, kw_len, subst_count, old_len, new_len; 802189959Skib 803249525Skib kw_len = strlen(kw); 804249525Skib 805249525Skib /* 806249525Skib * First, count the number of the keyword occurences, to 807249525Skib * preallocate the final string. 808249525Skib */ 809249525Skib for (p = real, subst_count = 0;; p = p1 + kw_len, subst_count++) { 810249525Skib p1 = strstr(p, kw); 811249525Skib if (p1 == NULL) 812249525Skib break; 813249525Skib } 814249525Skib 815249525Skib /* 816249525Skib * If the keyword is not found, just return. 817282412Skib * 818282412Skib * Return non-substituted string if resolution failed. We 819282412Skib * cannot do anything more reasonable, the failure mode of the 820282412Skib * caller is unresolved library anyway. 821249525Skib */ 822282412Skib if (subst_count == 0 || (obj != NULL && !obj_resolve_origin(obj))) 823249525Skib return (may_free ? real : xstrdup(real)); 824282412Skib if (obj != NULL) 825282412Skib subst = obj->origin_path; 826249525Skib 827249525Skib /* 828249525Skib * There is indeed something to substitute. Calculate the 829249525Skib * length of the resulting string, and allocate it. 830249525Skib */ 831249525Skib subst_len = strlen(subst); 832249525Skib old_len = strlen(real); 833249525Skib new_len = old_len + (subst_len - kw_len) * subst_count; 834249525Skib res = xmalloc(new_len + 1); 835249525Skib 836249525Skib /* 837249525Skib * Now, execute the substitution loop. 838249525Skib */ 839250075Skib for (p = real, resp = res, *resp = '\0';;) { 840249525Skib p1 = strstr(p, kw); 841249525Skib if (p1 != NULL) { 842249525Skib /* Copy the prefix before keyword. */ 843249525Skib memcpy(resp, p, p1 - p); 844249525Skib resp += p1 - p; 845249525Skib /* Keyword replacement. */ 846249525Skib memcpy(resp, subst, subst_len); 847249525Skib resp += subst_len; 848250075Skib *resp = '\0'; 849249525Skib p = p1 + kw_len; 850249525Skib } else 851249525Skib break; 852249525Skib } 853249525Skib 854249525Skib /* Copy to the end of string and finish. */ 855249525Skib strcat(resp, p); 856249525Skib if (may_free) 857249525Skib free(real); 858249525Skib return (res); 859189959Skib} 860189959Skib 861189959Skibstatic char * 862282412Skiborigin_subst(Obj_Entry *obj, char *real) 863189959Skib{ 864249525Skib char *res1, *res2, *res3, *res4; 865189959Skib 866282412Skib if (obj == NULL || !trust) 867282412Skib return (xstrdup(real)); 868249525Skib if (uts.sysname[0] == '\0') { 869249525Skib if (uname(&uts) != 0) { 870249525Skib _rtld_error("utsname failed: %d", errno); 871249525Skib return (NULL); 872249525Skib } 873189959Skib } 874282412Skib res1 = origin_subst_one(obj, real, "$ORIGIN", NULL, false); 875282412Skib res2 = origin_subst_one(NULL, res1, "$OSNAME", uts.sysname, true); 876282412Skib res3 = origin_subst_one(NULL, res2, "$OSREL", uts.release, true); 877282412Skib res4 = origin_subst_one(NULL, res3, "$PLATFORM", uts.machine, true); 878249525Skib return (res4); 879189959Skib} 880189959Skib 881282118Semastevoid 882282118Semastertld_die(void) 88334192Sjdp{ 88434192Sjdp const char *msg = dlerror(); 88534192Sjdp 88634192Sjdp if (msg == NULL) 88734192Sjdp msg = "Fatal error"; 888225152Skib rtld_fdputstr(STDERR_FILENO, msg); 889231582Skib rtld_fdputchar(STDERR_FILENO, '\n'); 890225152Skib _exit(1); 89134192Sjdp} 89234192Sjdp 89334192Sjdp/* 89434192Sjdp * Process a shared object's DYNAMIC section, and save the important 89534192Sjdp * information in its Obj_Entry structure. 89634192Sjdp */ 89734192Sjdpstatic void 898211413Skibdigest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath, 899238471Skib const Elf_Dyn **dyn_soname, const Elf_Dyn **dyn_runpath) 90034192Sjdp{ 90138816Sdfr const Elf_Dyn *dynp; 90234192Sjdp Needed_Entry **needed_tail = &obj->needed; 903216695Skib Needed_Entry **needed_filtees_tail = &obj->needed_filtees; 904216695Skib Needed_Entry **needed_aux_filtees_tail = &obj->needed_aux_filtees; 905234841Skib const Elf_Hashelt *hashtab; 906234841Skib const Elf32_Word *hashval; 907234841Skib Elf32_Word bkt, nmaskwords; 908234841Skib int bloom_size32; 90938816Sdfr int plttype = DT_REL; 91034192Sjdp 911211413Skib *dyn_rpath = NULL; 912211413Skib *dyn_soname = NULL; 913238471Skib *dyn_runpath = NULL; 914211413Skib 915124020Sdfr obj->bind_now = false; 91634192Sjdp for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; dynp++) { 91734192Sjdp switch (dynp->d_tag) { 91834192Sjdp 91934192Sjdp case DT_REL: 92038816Sdfr obj->rel = (const Elf_Rel *) (obj->relocbase + dynp->d_un.d_ptr); 92134192Sjdp break; 92234192Sjdp 92334192Sjdp case DT_RELSZ: 92434192Sjdp obj->relsize = dynp->d_un.d_val; 92534192Sjdp break; 92634192Sjdp 92734192Sjdp case DT_RELENT: 92838816Sdfr assert(dynp->d_un.d_val == sizeof(Elf_Rel)); 92934192Sjdp break; 93034192Sjdp 93134192Sjdp case DT_JMPREL: 93238816Sdfr obj->pltrel = (const Elf_Rel *) 93334192Sjdp (obj->relocbase + dynp->d_un.d_ptr); 93434192Sjdp break; 93534192Sjdp 93634192Sjdp case DT_PLTRELSZ: 93734192Sjdp obj->pltrelsize = dynp->d_un.d_val; 93834192Sjdp break; 93934192Sjdp 94034192Sjdp case DT_RELA: 94138816Sdfr obj->rela = (const Elf_Rela *) (obj->relocbase + dynp->d_un.d_ptr); 94238816Sdfr break; 94338816Sdfr 94434192Sjdp case DT_RELASZ: 94538816Sdfr obj->relasize = dynp->d_un.d_val; 94638816Sdfr break; 94738816Sdfr 94834192Sjdp case DT_RELAENT: 94938816Sdfr assert(dynp->d_un.d_val == sizeof(Elf_Rela)); 95034192Sjdp break; 95134192Sjdp 95234192Sjdp case DT_PLTREL: 95338816Sdfr plttype = dynp->d_un.d_val; 95438816Sdfr assert(dynp->d_un.d_val == DT_REL || plttype == DT_RELA); 95534192Sjdp break; 95634192Sjdp 95734192Sjdp case DT_SYMTAB: 95838816Sdfr obj->symtab = (const Elf_Sym *) 95934192Sjdp (obj->relocbase + dynp->d_un.d_ptr); 96034192Sjdp break; 96134192Sjdp 96234192Sjdp case DT_SYMENT: 96338816Sdfr assert(dynp->d_un.d_val == sizeof(Elf_Sym)); 96434192Sjdp break; 96534192Sjdp 96634192Sjdp case DT_STRTAB: 96734192Sjdp obj->strtab = (const char *) (obj->relocbase + dynp->d_un.d_ptr); 96834192Sjdp break; 96934192Sjdp 97034192Sjdp case DT_STRSZ: 97134192Sjdp obj->strsize = dynp->d_un.d_val; 97234192Sjdp break; 97334192Sjdp 974153515Skan case DT_VERNEED: 975153515Skan obj->verneed = (const Elf_Verneed *) (obj->relocbase + 976153515Skan dynp->d_un.d_val); 977153515Skan break; 978153515Skan 979153515Skan case DT_VERNEEDNUM: 980153515Skan obj->verneednum = dynp->d_un.d_val; 981153515Skan break; 982153515Skan 983153515Skan case DT_VERDEF: 984153515Skan obj->verdef = (const Elf_Verdef *) (obj->relocbase + 985153515Skan dynp->d_un.d_val); 986153515Skan break; 987153515Skan 988153515Skan case DT_VERDEFNUM: 989153515Skan obj->verdefnum = dynp->d_un.d_val; 990153515Skan break; 991153515Skan 992153515Skan case DT_VERSYM: 993153515Skan obj->versyms = (const Elf_Versym *)(obj->relocbase + 994153515Skan dynp->d_un.d_val); 995153515Skan break; 996153515Skan 99734192Sjdp case DT_HASH: 99834192Sjdp { 999234841Skib hashtab = (const Elf_Hashelt *)(obj->relocbase + 1000234841Skib dynp->d_un.d_ptr); 100134192Sjdp obj->nbuckets = hashtab[0]; 100234192Sjdp obj->nchains = hashtab[1]; 100334192Sjdp obj->buckets = hashtab + 2; 100434192Sjdp obj->chains = obj->buckets + obj->nbuckets; 1005234841Skib obj->valid_hash_sysv = obj->nbuckets > 0 && obj->nchains > 0 && 1006234841Skib obj->buckets != NULL; 100734192Sjdp } 100834192Sjdp break; 100934192Sjdp 1010234841Skib case DT_GNU_HASH: 1011234841Skib { 1012234841Skib hashtab = (const Elf_Hashelt *)(obj->relocbase + 1013234841Skib dynp->d_un.d_ptr); 1014234841Skib obj->nbuckets_gnu = hashtab[0]; 1015234841Skib obj->symndx_gnu = hashtab[1]; 1016234841Skib nmaskwords = hashtab[2]; 1017234841Skib bloom_size32 = (__ELF_WORD_SIZE / 32) * nmaskwords; 1018234841Skib obj->maskwords_bm_gnu = nmaskwords - 1; 1019234841Skib obj->shift2_gnu = hashtab[3]; 1020234841Skib obj->bloom_gnu = (Elf_Addr *) (hashtab + 4); 1021234841Skib obj->buckets_gnu = hashtab + 4 + bloom_size32; 1022234841Skib obj->chain_zero_gnu = obj->buckets_gnu + obj->nbuckets_gnu - 1023234841Skib obj->symndx_gnu; 1024278309Skib /* Number of bitmask words is required to be power of 2 */ 1025278309Skib obj->valid_hash_gnu = powerof2(nmaskwords) && 1026278309Skib obj->nbuckets_gnu > 0 && obj->buckets_gnu != NULL; 1027234841Skib } 1028234841Skib break; 1029234841Skib 103034192Sjdp case DT_NEEDED: 103145501Sjdp if (!obj->rtld) { 103234192Sjdp Needed_Entry *nep = NEW(Needed_Entry); 103334192Sjdp nep->name = dynp->d_un.d_val; 103434192Sjdp nep->obj = NULL; 103534192Sjdp nep->next = NULL; 103634192Sjdp 103734192Sjdp *needed_tail = nep; 103834192Sjdp needed_tail = &nep->next; 103934192Sjdp } 104034192Sjdp break; 104134192Sjdp 1042216695Skib case DT_FILTER: 1043216695Skib if (!obj->rtld) { 1044216695Skib Needed_Entry *nep = NEW(Needed_Entry); 1045216695Skib nep->name = dynp->d_un.d_val; 1046216695Skib nep->obj = NULL; 1047216695Skib nep->next = NULL; 1048216695Skib 1049216695Skib *needed_filtees_tail = nep; 1050216695Skib needed_filtees_tail = &nep->next; 1051216695Skib } 1052216695Skib break; 1053216695Skib 1054216695Skib case DT_AUXILIARY: 1055216695Skib if (!obj->rtld) { 1056216695Skib Needed_Entry *nep = NEW(Needed_Entry); 1057216695Skib nep->name = dynp->d_un.d_val; 1058216695Skib nep->obj = NULL; 1059216695Skib nep->next = NULL; 1060216695Skib 1061216695Skib *needed_aux_filtees_tail = nep; 1062216695Skib needed_aux_filtees_tail = &nep->next; 1063216695Skib } 1064216695Skib break; 1065216695Skib 106634192Sjdp case DT_PLTGOT: 106745501Sjdp obj->pltgot = (Elf_Addr *) (obj->relocbase + dynp->d_un.d_ptr); 106834192Sjdp break; 106934192Sjdp 107034192Sjdp case DT_TEXTREL: 107134192Sjdp obj->textrel = true; 107234192Sjdp break; 107334192Sjdp 107434192Sjdp case DT_SYMBOLIC: 107534192Sjdp obj->symbolic = true; 107634192Sjdp break; 107734192Sjdp 107834192Sjdp case DT_RPATH: 107934192Sjdp /* 108034192Sjdp * We have to wait until later to process this, because we 108134192Sjdp * might not have gotten the address of the string table yet. 108234192Sjdp */ 1083211413Skib *dyn_rpath = dynp; 108434192Sjdp break; 108534192Sjdp 108634192Sjdp case DT_SONAME: 1087211413Skib *dyn_soname = dynp; 108834192Sjdp break; 108934192Sjdp 1090238471Skib case DT_RUNPATH: 1091238471Skib *dyn_runpath = dynp; 1092238471Skib break; 1093238471Skib 109434192Sjdp case DT_INIT: 109585677Speter obj->init = (Elf_Addr) (obj->relocbase + dynp->d_un.d_ptr); 109634192Sjdp break; 109734192Sjdp 1098232831Skib case DT_PREINIT_ARRAY: 1099232831Skib obj->preinit_array = (Elf_Addr)(obj->relocbase + dynp->d_un.d_ptr); 1100232831Skib break; 1101232831Skib 1102232831Skib case DT_PREINIT_ARRAYSZ: 1103232831Skib obj->preinit_array_num = dynp->d_un.d_val / sizeof(Elf_Addr); 1104232831Skib break; 1105232831Skib 1106232831Skib case DT_INIT_ARRAY: 1107232831Skib obj->init_array = (Elf_Addr)(obj->relocbase + dynp->d_un.d_ptr); 1108232831Skib break; 1109232831Skib 1110232831Skib case DT_INIT_ARRAYSZ: 1111232831Skib obj->init_array_num = dynp->d_un.d_val / sizeof(Elf_Addr); 1112232831Skib break; 1113232831Skib 111434192Sjdp case DT_FINI: 111585677Speter obj->fini = (Elf_Addr) (obj->relocbase + dynp->d_un.d_ptr); 111634192Sjdp break; 111734192Sjdp 1118232831Skib case DT_FINI_ARRAY: 1119232831Skib obj->fini_array = (Elf_Addr)(obj->relocbase + dynp->d_un.d_ptr); 1120232831Skib break; 1121232831Skib 1122232831Skib case DT_FINI_ARRAYSZ: 1123232831Skib obj->fini_array_num = dynp->d_un.d_val / sizeof(Elf_Addr); 1124232831Skib break; 1125232831Skib 1126177924Simp /* 1127177924Simp * Don't process DT_DEBUG on MIPS as the dynamic section 1128177924Simp * is mapped read-only. DT_MIPS_RLD_MAP is used instead. 1129177924Simp */ 1130177924Simp 1131177924Simp#ifndef __mips__ 113234192Sjdp case DT_DEBUG: 113393610Sjake if (!early) 113493610Sjake dbg("Filling in DT_DEBUG entry"); 113538816Sdfr ((Elf_Dyn*)dynp)->d_un.d_ptr = (Elf_Addr) &r_debug; 113634192Sjdp break; 1137177924Simp#endif 113838816Sdfr 1139116511Smdodd case DT_FLAGS: 1140282412Skib if (dynp->d_un.d_val & DF_ORIGIN) 1141189959Skib obj->z_origin = true; 1142116511Smdodd if (dynp->d_un.d_val & DF_SYMBOLIC) 1143116511Smdodd obj->symbolic = true; 1144116511Smdodd if (dynp->d_un.d_val & DF_TEXTREL) 1145116511Smdodd obj->textrel = true; 1146116511Smdodd if (dynp->d_un.d_val & DF_BIND_NOW) 1147116511Smdodd obj->bind_now = true; 1148223262Sbenl /*if (dynp->d_un.d_val & DF_STATIC_TLS) 1149223262Sbenl ;*/ 1150116511Smdodd break; 1151177924Simp#ifdef __mips__ 1152177924Simp case DT_MIPS_LOCAL_GOTNO: 1153177924Simp obj->local_gotno = dynp->d_un.d_val; 1154177924Simp break; 1155116511Smdodd 1156177924Simp case DT_MIPS_SYMTABNO: 1157177924Simp obj->symtabno = dynp->d_un.d_val; 1158177924Simp break; 1159177924Simp 1160177924Simp case DT_MIPS_GOTSYM: 1161177924Simp obj->gotsym = dynp->d_un.d_val; 1162177924Simp break; 1163177924Simp 1164177924Simp case DT_MIPS_RLD_MAP: 1165255983Semaste *((Elf_Addr *)(dynp->d_un.d_ptr)) = (Elf_Addr) &r_debug; 1166177924Simp break; 1167177924Simp#endif 1168177924Simp 1169189959Skib case DT_FLAGS_1: 1170199829Skib if (dynp->d_un.d_val & DF_1_NOOPEN) 1171199829Skib obj->z_noopen = true; 1172282412Skib if (dynp->d_un.d_val & DF_1_ORIGIN) 1173189959Skib obj->z_origin = true; 1174281849Skib if (dynp->d_un.d_val & DF_1_GLOBAL) 1175281849Skib obj->z_global = true; 1176189959Skib if (dynp->d_un.d_val & DF_1_BIND_NOW) 1177189959Skib obj->bind_now = true; 1178190543Skib if (dynp->d_un.d_val & DF_1_NODELETE) 1179190543Skib obj->z_nodelete = true; 1180216695Skib if (dynp->d_un.d_val & DF_1_LOADFLTR) 1181216695Skib obj->z_loadfltr = true; 1182256101Skib if (dynp->d_un.d_val & DF_1_INTERPOSE) 1183256101Skib obj->z_interpose = true; 1184238471Skib if (dynp->d_un.d_val & DF_1_NODEFLIB) 1185238471Skib obj->z_nodeflib = true; 1186189959Skib break; 1187189959Skib 118838816Sdfr default: 118993610Sjake if (!early) { 119093610Sjake dbg("Ignoring d_tag %ld = %#lx", (long)dynp->d_tag, 119193610Sjake (long)dynp->d_tag); 119293610Sjake } 119350928Sjdp break; 119434192Sjdp } 119534192Sjdp } 119634192Sjdp 119738816Sdfr obj->traced = false; 119838816Sdfr 119938816Sdfr if (plttype == DT_RELA) { 120038816Sdfr obj->pltrela = (const Elf_Rela *) obj->pltrel; 120138816Sdfr obj->pltrel = NULL; 120238816Sdfr obj->pltrelasize = obj->pltrelsize; 120338816Sdfr obj->pltrelsize = 0; 120438816Sdfr } 1205234841Skib 1206234841Skib /* Determine size of dynsym table (equal to nchains of sysv hash) */ 1207234841Skib if (obj->valid_hash_sysv) 1208234841Skib obj->dynsymcount = obj->nchains; 1209234841Skib else if (obj->valid_hash_gnu) { 1210234841Skib obj->dynsymcount = 0; 1211234841Skib for (bkt = 0; bkt < obj->nbuckets_gnu; bkt++) { 1212234841Skib if (obj->buckets_gnu[bkt] == 0) 1213234841Skib continue; 1214234841Skib hashval = &obj->chain_zero_gnu[obj->buckets_gnu[bkt]]; 1215234841Skib do 1216234841Skib obj->dynsymcount++; 1217234841Skib while ((*hashval++ & 1u) == 0); 1218234841Skib } 1219234841Skib obj->dynsymcount += obj->symndx_gnu; 1220234841Skib } 1221211413Skib} 122238816Sdfr 1223282412Skibstatic bool 1224282412Skibobj_resolve_origin(Obj_Entry *obj) 1225282412Skib{ 1226282412Skib 1227282412Skib if (obj->origin_path != NULL) 1228282412Skib return (true); 1229282412Skib obj->origin_path = xmalloc(PATH_MAX); 1230282412Skib return (rtld_dirname_abs(obj->path, obj->origin_path) != -1); 1231282412Skib} 1232282412Skib 1233211413Skibstatic void 1234211413Skibdigest_dynamic2(Obj_Entry *obj, const Elf_Dyn *dyn_rpath, 1235238471Skib const Elf_Dyn *dyn_soname, const Elf_Dyn *dyn_runpath) 1236211413Skib{ 1237211413Skib 1238282412Skib if (obj->z_origin && !obj_resolve_origin(obj)) 1239282412Skib rtld_die(); 1240153515Skan 1241282412Skib if (dyn_runpath != NULL) { 1242282412Skib obj->runpath = (char *)obj->strtab + dyn_runpath->d_un.d_val; 1243282412Skib obj->runpath = origin_subst(obj, obj->runpath); 1244282412Skib } else if (dyn_rpath != NULL) { 1245282412Skib obj->rpath = (char *)obj->strtab + dyn_rpath->d_un.d_val; 1246282412Skib obj->rpath = origin_subst(obj, obj->rpath); 1247282412Skib } 1248282412Skib if (dyn_soname != NULL) 1249282412Skib object_add_name(obj, obj->strtab + dyn_soname->d_un.d_val); 125034192Sjdp} 125134192Sjdp 1252211413Skibstatic void 1253211413Skibdigest_dynamic(Obj_Entry *obj, int early) 1254211413Skib{ 1255211413Skib const Elf_Dyn *dyn_rpath; 1256211413Skib const Elf_Dyn *dyn_soname; 1257238471Skib const Elf_Dyn *dyn_runpath; 1258211413Skib 1259238471Skib digest_dynamic1(obj, early, &dyn_rpath, &dyn_soname, &dyn_runpath); 1260238471Skib digest_dynamic2(obj, dyn_rpath, dyn_soname, dyn_runpath); 1261211413Skib} 1262211413Skib 126334192Sjdp/* 126434192Sjdp * Process a shared object's program header. This is used only for the 126534192Sjdp * main program, when the kernel has already loaded the main program 126634192Sjdp * into memory before calling the dynamic linker. It creates and 126734192Sjdp * returns an Obj_Entry structure. 126834192Sjdp */ 126934192Sjdpstatic Obj_Entry * 127048871Sjdpdigest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry, const char *path) 127134192Sjdp{ 127250608Sjdp Obj_Entry *obj; 127338816Sdfr const Elf_Phdr *phlimit = phdr + phnum; 127438816Sdfr const Elf_Phdr *ph; 1275232831Skib Elf_Addr note_start, note_end; 127634192Sjdp int nsegs = 0; 127734192Sjdp 127850608Sjdp obj = obj_new(); 127934192Sjdp for (ph = phdr; ph < phlimit; ph++) { 1280197931Skib if (ph->p_type != PT_PHDR) 1281197931Skib continue; 1282197931Skib 1283197931Skib obj->phdr = phdr; 1284197931Skib obj->phsize = ph->p_memsz; 1285197931Skib obj->relocbase = (caddr_t)phdr - ph->p_vaddr; 1286197931Skib break; 1287197931Skib } 1288197931Skib 1289217153Skib obj->stack_flags = PF_X | PF_R | PF_W; 1290217153Skib 1291197931Skib for (ph = phdr; ph < phlimit; ph++) { 129234192Sjdp switch (ph->p_type) { 129334192Sjdp 129450610Sjdp case PT_INTERP: 1295197931Skib obj->interp = (const char *)(ph->p_vaddr + obj->relocbase); 129650610Sjdp break; 129750610Sjdp 129834192Sjdp case PT_LOAD: 129934192Sjdp if (nsegs == 0) { /* First load segment */ 130034192Sjdp obj->vaddrbase = trunc_page(ph->p_vaddr); 1301197931Skib obj->mapbase = obj->vaddrbase + obj->relocbase; 130234192Sjdp obj->textsize = round_page(ph->p_vaddr + ph->p_memsz) - 130334192Sjdp obj->vaddrbase; 130434192Sjdp } else { /* Last load segment */ 130534192Sjdp obj->mapsize = round_page(ph->p_vaddr + ph->p_memsz) - 130634192Sjdp obj->vaddrbase; 130734192Sjdp } 130834192Sjdp nsegs++; 130934192Sjdp break; 131034192Sjdp 131134192Sjdp case PT_DYNAMIC: 1312197931Skib obj->dynamic = (const Elf_Dyn *)(ph->p_vaddr + obj->relocbase); 131334192Sjdp break; 1314133063Sdfr 1315133063Sdfr case PT_TLS: 1316133063Sdfr obj->tlsindex = 1; 1317133063Sdfr obj->tlssize = ph->p_memsz; 1318133063Sdfr obj->tlsalign = ph->p_align; 1319133063Sdfr obj->tlsinitsize = ph->p_filesz; 1320197931Skib obj->tlsinit = (void*)(ph->p_vaddr + obj->relocbase); 1321133063Sdfr break; 1322217153Skib 1323217153Skib case PT_GNU_STACK: 1324217153Skib obj->stack_flags = ph->p_flags; 1325217153Skib break; 1326230784Skib 1327230784Skib case PT_GNU_RELRO: 1328230784Skib obj->relro_page = obj->relocbase + trunc_page(ph->p_vaddr); 1329230784Skib obj->relro_size = round_page(ph->p_memsz); 1330230784Skib break; 1331232831Skib 1332232831Skib case PT_NOTE: 1333232831Skib note_start = (Elf_Addr)obj->relocbase + ph->p_vaddr; 1334232831Skib note_end = note_start + ph->p_filesz; 1335232831Skib digest_notes(obj, note_start, note_end); 1336232831Skib break; 133734192Sjdp } 133834192Sjdp } 1339107390Skan if (nsegs < 1) { 1340107390Skan _rtld_error("%s: too few PT_LOAD segments", path); 1341107390Skan return NULL; 1342107390Skan } 134334192Sjdp 134434192Sjdp obj->entry = entry; 134534192Sjdp return obj; 134634192Sjdp} 134734192Sjdp 1348232831Skibvoid 1349232831Skibdigest_notes(Obj_Entry *obj, Elf_Addr note_start, Elf_Addr note_end) 1350232831Skib{ 1351232831Skib const Elf_Note *note; 1352232831Skib const char *note_name; 1353232831Skib uintptr_t p; 1354232831Skib 1355232831Skib for (note = (const Elf_Note *)note_start; (Elf_Addr)note < note_end; 1356232831Skib note = (const Elf_Note *)((const char *)(note + 1) + 1357232831Skib roundup2(note->n_namesz, sizeof(Elf32_Addr)) + 1358232831Skib roundup2(note->n_descsz, sizeof(Elf32_Addr)))) { 1359232831Skib if (note->n_namesz != sizeof(NOTE_FREEBSD_VENDOR) || 1360232831Skib note->n_descsz != sizeof(int32_t)) 1361232831Skib continue; 1362232831Skib if (note->n_type != ABI_NOTETYPE && 1363232831Skib note->n_type != CRT_NOINIT_NOTETYPE) 1364232831Skib continue; 1365232831Skib note_name = (const char *)(note + 1); 1366232831Skib if (strncmp(NOTE_FREEBSD_VENDOR, note_name, 1367232831Skib sizeof(NOTE_FREEBSD_VENDOR)) != 0) 1368232831Skib continue; 1369232831Skib switch (note->n_type) { 1370232831Skib case ABI_NOTETYPE: 1371232831Skib /* FreeBSD osrel note */ 1372232831Skib p = (uintptr_t)(note + 1); 1373232831Skib p += roundup2(note->n_namesz, sizeof(Elf32_Addr)); 1374232831Skib obj->osrel = *(const int32_t *)(p); 1375232831Skib dbg("note osrel %d", obj->osrel); 1376232831Skib break; 1377232831Skib case CRT_NOINIT_NOTETYPE: 1378232831Skib /* FreeBSD 'crt does not call init' note */ 1379232831Skib obj->crt_no_init = true; 1380232831Skib dbg("note crt_no_init"); 1381232831Skib break; 1382232831Skib } 1383232831Skib } 1384232831Skib} 1385232831Skib 138634192Sjdpstatic Obj_Entry * 138734192Sjdpdlcheck(void *handle) 138834192Sjdp{ 138934192Sjdp Obj_Entry *obj; 139034192Sjdp 1391296727Skib TAILQ_FOREACH(obj, &obj_list, next) { 139234192Sjdp if (obj == (Obj_Entry *) handle) 139334192Sjdp break; 1394296727Skib } 139534192Sjdp 139670677Sjdp if (obj == NULL || obj->refcount == 0 || obj->dl_refcount == 0) { 139734192Sjdp _rtld_error("Invalid shared object handle %p", handle); 139834192Sjdp return NULL; 139934192Sjdp } 140034192Sjdp return obj; 140134192Sjdp} 140234192Sjdp 140334192Sjdp/* 140462801Sjdp * If the given object is already in the donelist, return true. Otherwise 140562801Sjdp * add the object to the list and return false. 140662801Sjdp */ 140762801Sjdpstatic bool 140866056Sjdpdonelist_check(DoneList *dlp, const Obj_Entry *obj) 140962801Sjdp{ 141062801Sjdp unsigned int i; 141162801Sjdp 141262801Sjdp for (i = 0; i < dlp->num_used; i++) 141362801Sjdp if (dlp->objs[i] == obj) 141462801Sjdp return true; 141562801Sjdp /* 141662801Sjdp * Our donelist allocation should always be sufficient. But if 141762801Sjdp * our threads locking isn't working properly, more shared objects 141862801Sjdp * could have been loaded since we allocated the list. That should 141962801Sjdp * never happen, but we'll handle it properly just in case it does. 142062801Sjdp */ 142162801Sjdp if (dlp->num_used < dlp->num_alloc) 142262801Sjdp dlp->objs[dlp->num_used++] = obj; 142362801Sjdp return false; 142462801Sjdp} 142562801Sjdp 142662801Sjdp/* 142734192Sjdp * Hash function for symbol table lookup. Don't even think about changing 142834192Sjdp * this. It is specified by the System V ABI. 142934192Sjdp */ 143038816Sdfrunsigned long 143134192Sjdpelf_hash(const char *name) 143234192Sjdp{ 143334192Sjdp const unsigned char *p = (const unsigned char *) name; 143434192Sjdp unsigned long h = 0; 143534192Sjdp unsigned long g; 143634192Sjdp 143734192Sjdp while (*p != '\0') { 143834192Sjdp h = (h << 4) + *p++; 143934192Sjdp if ((g = h & 0xf0000000) != 0) 144034192Sjdp h ^= g >> 24; 144134192Sjdp h &= ~g; 144234192Sjdp } 144334192Sjdp return h; 144434192Sjdp} 144534192Sjdp 144634192Sjdp/* 1447234841Skib * The GNU hash function is the Daniel J. Bernstein hash clipped to 32 bits 1448234841Skib * unsigned in case it's implemented with a wider type. 1449234841Skib */ 1450234841Skibstatic uint32_t 1451234841Skibgnu_hash(const char *s) 1452234841Skib{ 1453234841Skib uint32_t h; 1454234841Skib unsigned char c; 1455234841Skib 1456234841Skib h = 5381; 1457234841Skib for (c = *s; c != '\0'; c = *++s) 1458234841Skib h = h * 33 + c; 1459234841Skib return (h & 0xffffffff); 1460234841Skib} 1461234841Skib 1462234841Skib/* 146334192Sjdp * Find the library with the given name, and return its full pathname. 146434192Sjdp * The returned string is dynamically allocated. Generates an error 146534192Sjdp * message and returns NULL if the library cannot be found. 146634192Sjdp * 146734192Sjdp * If the second argument is non-NULL, then it refers to an already- 146834192Sjdp * loaded shared object, whose library search path will be searched. 146938836Sjdp * 147038836Sjdp * The search order is: 1471238471Skib * DT_RPATH in the referencing file _unless_ DT_RUNPATH is present (1) 1472238471Skib * DT_RPATH of the main object if DSO without defined DT_RUNPATH (1) 1473122665Stobez * LD_LIBRARY_PATH 1474238471Skib * DT_RUNPATH in the referencing file 1475238471Skib * ldconfig hints (if -z nodefaultlib, filter out default library directories 1476238471Skib * from list) 1477238471Skib * /lib:/usr/lib _unless_ the referencing file is linked with -z nodefaultlib 1478238471Skib * 1479238471Skib * (1) Handled in digest_dynamic2 - rpath left NULL if runpath defined. 148034192Sjdp */ 148134192Sjdpstatic char * 1482113229Smdoddfind_library(const char *xname, const Obj_Entry *refobj) 148334192Sjdp{ 148434192Sjdp char *pathname; 1485113229Smdodd char *name; 1486240686Skib bool nodeflib, objgiven; 148734192Sjdp 1488238471Skib objgiven = refobj != NULL; 1489113229Smdodd if (strchr(xname, '/') != NULL) { /* Hard coded pathname */ 1490113229Smdodd if (xname[0] != '/' && !trust) { 149134192Sjdp _rtld_error("Absolute pathname required for shared object \"%s\"", 1492113229Smdodd xname); 149334192Sjdp return NULL; 149434192Sjdp } 1495282412Skib return (origin_subst(__DECONST(Obj_Entry *, refobj), 1496282412Skib __DECONST(char *, xname))); 149734192Sjdp } 149834192Sjdp 1499238471Skib if (libmap_disable || !objgiven || 1500116539Smdodd (name = lm_find(refobj->path, xname)) == NULL) 1501113229Smdodd name = (char *)xname; 1502113229Smdodd 150334192Sjdp dbg(" Searching for \"%s\"", name); 150434192Sjdp 1505238471Skib /* 1506238471Skib * If refobj->rpath != NULL, then refobj->runpath is NULL. Fall 1507238471Skib * back to pre-conforming behaviour if user requested so with 1508238471Skib * LD_LIBRARY_PATH_RPATH environment variable and ignore -z 1509238471Skib * nodeflib. 1510238471Skib */ 1511238471Skib if (objgiven && refobj->rpath != NULL && ld_library_path_rpath) { 1512238471Skib if ((pathname = search_library_path(name, ld_library_path)) != NULL || 1513238471Skib (refobj != NULL && 1514238471Skib (pathname = search_library_path(name, refobj->rpath)) != NULL) || 1515238471Skib (pathname = search_library_path(name, gethints(false))) != NULL || 1516238471Skib (pathname = search_library_path(name, STANDARD_LIBRARY_PATH)) != NULL) 1517238471Skib return (pathname); 1518238471Skib } else { 1519240686Skib nodeflib = objgiven ? refobj->z_nodeflib : false; 1520238471Skib if ((objgiven && 1521238471Skib (pathname = search_library_path(name, refobj->rpath)) != NULL) || 1522238471Skib (objgiven && refobj->runpath == NULL && refobj != obj_main && 1523238471Skib (pathname = search_library_path(name, obj_main->rpath)) != NULL) || 1524238471Skib (pathname = search_library_path(name, ld_library_path)) != NULL || 1525238471Skib (objgiven && 1526238471Skib (pathname = search_library_path(name, refobj->runpath)) != NULL) || 1527240686Skib (pathname = search_library_path(name, gethints(nodeflib))) != NULL || 1528240686Skib (objgiven && !nodeflib && 1529238471Skib (pathname = search_library_path(name, STANDARD_LIBRARY_PATH)) != NULL)) 1530238471Skib return (pathname); 1531238471Skib } 153234192Sjdp 1533238471Skib if (objgiven && refobj->path != NULL) { 1534129792Seik _rtld_error("Shared object \"%s\" not found, required by \"%s\"", 1535129792Seik name, basename(refobj->path)); 1536129792Seik } else { 1537129792Seik _rtld_error("Shared object \"%s\" not found", name); 1538129792Seik } 153934192Sjdp return NULL; 154034192Sjdp} 154134192Sjdp 154234192Sjdp/* 154334192Sjdp * Given a symbol number in a referencing object, find the corresponding 154434192Sjdp * definition of the symbol. Returns a pointer to the symbol, or NULL if 154534192Sjdp * no definition was found. Returns a pointer to the Obj_Entry of the 154634192Sjdp * defining object via the reference parameter DEFOBJ_OUT. 154734192Sjdp */ 154838816Sdfrconst Elf_Sym * 154966056Sjdpfind_symdef(unsigned long symnum, const Obj_Entry *refobj, 1550216695Skib const Obj_Entry **defobj_out, int flags, SymCache *cache, 1551216695Skib RtldLockState *lockstate) 155234192Sjdp{ 155338816Sdfr const Elf_Sym *ref; 155450606Sjdp const Elf_Sym *def; 155550606Sjdp const Obj_Entry *defobj; 1556320888Skib const Ver_Entry *ve; 1557216695Skib SymLook req; 155834192Sjdp const char *name; 1559216695Skib int res; 156034192Sjdp 156176296Sjdp /* 156276296Sjdp * If we have already found this symbol, get the information from 156376296Sjdp * the cache. 156476296Sjdp */ 1565234841Skib if (symnum >= refobj->dynsymcount) 156676296Sjdp return NULL; /* Bad object */ 156776296Sjdp if (cache != NULL && cache[symnum].sym != NULL) { 156876296Sjdp *defobj_out = cache[symnum].obj; 156976296Sjdp return cache[symnum].sym; 157076296Sjdp } 157176296Sjdp 157234192Sjdp ref = refobj->symtab + symnum; 157334192Sjdp name = refobj->strtab + ref->st_name; 1574216695Skib def = NULL; 157550607Sjdp defobj = NULL; 1576320888Skib ve = NULL; 157734192Sjdp 157895539Smarcel /* 157995539Smarcel * We don't have to do a full scale lookup if the symbol is local. 158095539Smarcel * We know it will bind to the instance in this load module; to 158195539Smarcel * which we already have a pointer (ie ref). By not doing a lookup, 158295539Smarcel * we not only improve performance, but it also avoids unresolvable 158395539Smarcel * symbols when local symbols are not in the hash table. This has 158495539Smarcel * been seen with the ia64 toolchain. 158595539Smarcel */ 158695539Smarcel if (ELF_ST_BIND(ref->st_info) != STB_LOCAL) { 158795539Smarcel if (ELF_ST_TYPE(ref->st_info) == STT_SECTION) { 158893610Sjake _rtld_error("%s: Bogus symbol table entry %lu", refobj->path, 158993610Sjake symnum); 159093610Sjake } 1591216695Skib symlook_init(&req, name); 1592216695Skib req.flags = flags; 1593320888Skib ve = req.ventry = fetch_ventry(refobj, symnum); 1594216695Skib req.lockstate = lockstate; 1595216695Skib res = symlook_default(&req, refobj); 1596216695Skib if (res == 0) { 1597216695Skib def = req.sym_out; 1598216695Skib defobj = req.defobj_out; 1599216695Skib } 160095539Smarcel } else { 160193610Sjake def = ref; 160293610Sjake defobj = refobj; 160395539Smarcel } 160434192Sjdp 160550606Sjdp /* 160650608Sjdp * If we found no definition and the reference is weak, treat the 160750606Sjdp * symbol as having the value zero. 160850606Sjdp */ 160950608Sjdp if (def == NULL && ELF_ST_BIND(ref->st_info) == STB_WEAK) { 161050608Sjdp def = &sym_zero; 161150608Sjdp defobj = obj_main; 161245320Sjdp } 161345320Sjdp 161476296Sjdp if (def != NULL) { 161550608Sjdp *defobj_out = defobj; 161676296Sjdp /* Record the information in the cache to avoid subsequent lookups. */ 161776296Sjdp if (cache != NULL) { 161876296Sjdp cache[symnum].sym = def; 161976296Sjdp cache[symnum].obj = defobj; 162076296Sjdp } 162185004Sdfr } else { 162285004Sdfr if (refobj != &obj_rtld) 1623320888Skib _rtld_error("%s: Undefined symbol \"%s%s%s\"", refobj->path, name, 1624320888Skib ve != NULL ? "@" : "", ve != NULL ? ve->name : ""); 162585004Sdfr } 162650608Sjdp return def; 162734192Sjdp} 162834192Sjdp 162934192Sjdp/* 163038836Sjdp * Return the search path from the ldconfig hints file, reading it if 1631238471Skib * necessary. If nostdlib is true, then the default search paths are 1632238471Skib * not added to result. 1633238471Skib * 1634238471Skib * Returns NULL if there are problems with the hints file, 163538836Sjdp * or if the search path there is empty. 163638836Sjdp */ 163738836Sjdpstatic const char * 1638238471Skibgethints(bool nostdlib) 163938836Sjdp{ 1640238471Skib static char *hints, *filtered_path; 1641301581Skib static struct elfhints_hdr hdr; 1642238471Skib struct fill_search_info_args sargs, hargs; 1643238471Skib struct dl_serinfo smeta, hmeta, *SLPinfo, *hintinfo; 1644238471Skib struct dl_serpath *SLPpath, *hintpath; 164538836Sjdp char *p; 1646301581Skib struct stat hint_stat; 1647238471Skib unsigned int SLPndx, hintndx, fndx, fcount; 1648238471Skib int fd; 1649238471Skib size_t flen; 1650301581Skib uint32_t dl; 1651238471Skib bool skip; 165238836Sjdp 1653238471Skib /* First call, read the hints file */ 1654238471Skib if (hints == NULL) { 1655238471Skib /* Keep from trying again in case the hints file is bad. */ 1656238471Skib hints = ""; 165738836Sjdp 1658242587Sjilles if ((fd = open(ld_elf_hints_path, O_RDONLY | O_CLOEXEC)) == -1) 1659238471Skib return (NULL); 1660301581Skib 1661301581Skib /* 1662301581Skib * Check of hdr.dirlistlen value against type limit 1663301581Skib * intends to pacify static analyzers. Further 1664301581Skib * paranoia leads to checks that dirlist is fully 1665301581Skib * contained in the file range. 1666301581Skib */ 1667238471Skib if (read(fd, &hdr, sizeof hdr) != sizeof hdr || 1668238471Skib hdr.magic != ELFHINTS_MAGIC || 1669301581Skib hdr.version != 1 || hdr.dirlistlen > UINT_MAX / 2 || 1670301581Skib fstat(fd, &hint_stat) == -1) { 1671301581Skibcleanup1: 1672238471Skib close(fd); 1673301581Skib hdr.dirlistlen = 0; 1674238471Skib return (NULL); 1675238471Skib } 1676301581Skib dl = hdr.strtab; 1677301581Skib if (dl + hdr.dirlist < dl) 1678301581Skib goto cleanup1; 1679301581Skib dl += hdr.dirlist; 1680301581Skib if (dl + hdr.dirlistlen < dl) 1681301581Skib goto cleanup1; 1682301581Skib dl += hdr.dirlistlen; 1683301581Skib if (dl > hint_stat.st_size) 1684301581Skib goto cleanup1; 1685238471Skib p = xmalloc(hdr.dirlistlen + 1); 1686301581Skib 1687238471Skib if (lseek(fd, hdr.strtab + hdr.dirlist, SEEK_SET) == -1 || 1688238471Skib read(fd, p, hdr.dirlistlen + 1) != 1689301581Skib (ssize_t)hdr.dirlistlen + 1 || p[hdr.dirlistlen] != '\0') { 1690238471Skib free(p); 1691301581Skib goto cleanup1; 1692238471Skib } 1693238471Skib hints = p; 1694238471Skib close(fd); 169538836Sjdp } 1696238471Skib 1697238471Skib /* 1698238471Skib * If caller agreed to receive list which includes the default 1699238471Skib * paths, we are done. Otherwise, if we still did not 1700238471Skib * calculated filtered result, do it now. 1701238471Skib */ 1702238471Skib if (!nostdlib) 1703238471Skib return (hints[0] != '\0' ? hints : NULL); 1704238471Skib if (filtered_path != NULL) 1705238471Skib goto filt_ret; 1706238471Skib 1707238471Skib /* 1708238471Skib * Obtain the list of all configured search paths, and the 1709238471Skib * list of the default paths. 1710238471Skib * 1711238471Skib * First estimate the size of the results. 1712238471Skib */ 1713238471Skib smeta.dls_size = __offsetof(struct dl_serinfo, dls_serpath); 1714238471Skib smeta.dls_cnt = 0; 1715238471Skib hmeta.dls_size = __offsetof(struct dl_serinfo, dls_serpath); 1716238471Skib hmeta.dls_cnt = 0; 1717238471Skib 1718238471Skib sargs.request = RTLD_DI_SERINFOSIZE; 1719238471Skib sargs.serinfo = &smeta; 1720238471Skib hargs.request = RTLD_DI_SERINFOSIZE; 1721238471Skib hargs.serinfo = &hmeta; 1722238471Skib 1723238471Skib path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &sargs); 1724301581Skib path_enumerate(hints, fill_search_info, &hargs); 1725238471Skib 1726238471Skib SLPinfo = xmalloc(smeta.dls_size); 1727238471Skib hintinfo = xmalloc(hmeta.dls_size); 1728238471Skib 1729238471Skib /* 1730238471Skib * Next fetch both sets of paths. 1731238471Skib */ 1732238471Skib sargs.request = RTLD_DI_SERINFO; 1733238471Skib sargs.serinfo = SLPinfo; 1734238471Skib sargs.serpath = &SLPinfo->dls_serpath[0]; 1735238471Skib sargs.strspace = (char *)&SLPinfo->dls_serpath[smeta.dls_cnt]; 1736238471Skib 1737238471Skib hargs.request = RTLD_DI_SERINFO; 1738238471Skib hargs.serinfo = hintinfo; 1739238471Skib hargs.serpath = &hintinfo->dls_serpath[0]; 1740238471Skib hargs.strspace = (char *)&hintinfo->dls_serpath[hmeta.dls_cnt]; 1741238471Skib 1742238471Skib path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &sargs); 1743301581Skib path_enumerate(hints, fill_search_info, &hargs); 1744238471Skib 1745238471Skib /* 1746238471Skib * Now calculate the difference between two sets, by excluding 1747238471Skib * standard paths from the full set. 1748238471Skib */ 1749238471Skib fndx = 0; 1750238471Skib fcount = 0; 1751238471Skib filtered_path = xmalloc(hdr.dirlistlen + 1); 1752238471Skib hintpath = &hintinfo->dls_serpath[0]; 1753238471Skib for (hintndx = 0; hintndx < hmeta.dls_cnt; hintndx++, hintpath++) { 1754238471Skib skip = false; 1755238471Skib SLPpath = &SLPinfo->dls_serpath[0]; 1756238471Skib /* 1757238471Skib * Check each standard path against current. 1758238471Skib */ 1759238471Skib for (SLPndx = 0; SLPndx < smeta.dls_cnt; SLPndx++, SLPpath++) { 1760238471Skib /* matched, skip the path */ 1761238471Skib if (!strcmp(hintpath->dls_name, SLPpath->dls_name)) { 1762238471Skib skip = true; 1763238471Skib break; 1764238471Skib } 1765238471Skib } 1766238471Skib if (skip) 1767238471Skib continue; 1768238471Skib /* 1769238471Skib * Not matched against any standard path, add the path 1770238471Skib * to result. Separate consequtive paths with ':'. 1771238471Skib */ 1772238471Skib if (fcount > 0) { 1773238471Skib filtered_path[fndx] = ':'; 1774238471Skib fndx++; 1775238471Skib } 1776238471Skib fcount++; 1777238471Skib flen = strlen(hintpath->dls_name); 1778238471Skib strncpy((filtered_path + fndx), hintpath->dls_name, flen); 1779238471Skib fndx += flen; 178038836Sjdp } 1781238471Skib filtered_path[fndx] = '\0'; 1782238471Skib 1783238471Skib free(SLPinfo); 1784238471Skib free(hintinfo); 1785238471Skib 1786238471Skibfilt_ret: 1787238471Skib return (filtered_path[0] != '\0' ? filtered_path : NULL); 178838836Sjdp} 178938836Sjdp 179050608Sjdpstatic void 179150608Sjdpinit_dag(Obj_Entry *root) 179250608Sjdp{ 1793218051Skan const Needed_Entry *needed; 1794218051Skan const Objlist_Entry *elm; 179562801Sjdp DoneList donelist; 179662801Sjdp 1797214728Skib if (root->dag_inited) 1798214776Skib return; 179962801Sjdp donelist_init(&donelist); 180050608Sjdp 1801218051Skan /* Root object belongs to own DAG. */ 1802218051Skan objlist_push_tail(&root->dldags, root); 1803218051Skan objlist_push_tail(&root->dagmembers, root); 1804218051Skan donelist_check(&donelist, root); 180550608Sjdp 1806218051Skan /* 1807218051Skan * Add dependencies of root object to DAG in breadth order 1808218051Skan * by exploiting the fact that each new object get added 1809218051Skan * to the tail of the dagmembers list. 1810218051Skan */ 1811218051Skan STAILQ_FOREACH(elm, &root->dagmembers, link) { 1812218051Skan for (needed = elm->obj->needed; needed != NULL; needed = needed->next) { 1813218051Skan if (needed->obj == NULL || donelist_check(&donelist, needed->obj)) 1814218051Skan continue; 1815218051Skan objlist_push_tail(&needed->obj->dldags, root); 1816218051Skan objlist_push_tail(&root->dagmembers, needed->obj); 1817218051Skan } 1818218051Skan } 1819218051Skan root->dag_inited = true; 182050608Sjdp} 182150608Sjdp 1822296727SkibObj_Entry * 1823296727Skibgloballist_curr(const Obj_Entry *obj) 1824296727Skib{ 1825296727Skib 1826296727Skib for (;;) { 1827296727Skib if (obj == NULL) 1828296727Skib return (NULL); 1829296727Skib if (!obj->marker) 1830296727Skib return (__DECONST(Obj_Entry *, obj)); 1831296727Skib obj = TAILQ_PREV(obj, obj_entry_q, next); 1832296727Skib } 1833296727Skib} 1834296727Skib 1835296727SkibObj_Entry * 1836296727Skibgloballist_next(const Obj_Entry *obj) 1837296727Skib{ 1838296727Skib 1839296727Skib for (;;) { 1840296727Skib obj = TAILQ_NEXT(obj, next); 1841296727Skib if (obj == NULL) 1842296727Skib return (NULL); 1843296727Skib if (!obj->marker) 1844296727Skib return (__DECONST(Obj_Entry *, obj)); 1845296727Skib } 1846296727Skib} 1847296727Skib 1848239253Skanstatic void 1849281849Skibprocess_z(Obj_Entry *root) 1850239253Skan{ 1851239253Skan const Objlist_Entry *elm; 1852281849Skib Obj_Entry *obj; 1853239253Skan 1854239253Skan /* 1855281849Skib * Walk over object DAG and process every dependent object 1856281849Skib * that is marked as DF_1_NODELETE or DF_1_GLOBAL. They need 1857281849Skib * to grow their own DAG. 1858281849Skib * 1859281849Skib * For DF_1_GLOBAL, DAG is required for symbol lookups in 1860281849Skib * symlook_global() to work. 1861281849Skib * 1862281849Skib * For DF_1_NODELETE, the DAG should have its reference upped. 1863239253Skan */ 1864239253Skan STAILQ_FOREACH(elm, &root->dagmembers, link) { 1865281849Skib obj = elm->obj; 1866281849Skib if (obj == NULL) 1867281849Skib continue; 1868281849Skib if (obj->z_nodelete && !obj->ref_nodel) { 1869281849Skib dbg("obj %s -z nodelete", obj->path); 1870281849Skib init_dag(obj); 1871281849Skib ref_dag(obj); 1872281849Skib obj->ref_nodel = true; 1873239253Skan } 1874281849Skib if (obj->z_global && objlist_find(&list_global, obj) == NULL) { 1875281849Skib dbg("obj %s -z global", obj->path); 1876281849Skib objlist_push_tail(&list_global, obj); 1877281849Skib init_dag(obj); 1878281849Skib } 1879239253Skan } 1880239253Skan} 188138836Sjdp/* 188234192Sjdp * Initialize the dynamic linker. The argument is the address at which 188334192Sjdp * the dynamic linker has been mapped into memory. The primary task of 188434192Sjdp * this function is to relocate the dynamic linker. 188534192Sjdp */ 188634192Sjdpstatic void 1887211413Skibinit_rtld(caddr_t mapbase, Elf_Auxinfo **aux_info) 188834192Sjdp{ 188993610Sjake Obj_Entry objtmp; /* Temporary rtld object */ 1890304455Skib const Elf_Ehdr *ehdr; 1891211413Skib const Elf_Dyn *dyn_rpath; 1892211413Skib const Elf_Dyn *dyn_soname; 1893238471Skib const Elf_Dyn *dyn_runpath; 189493610Sjake 1895281486Speter#ifdef RTLD_INIT_PAGESIZES_EARLY 1896281486Speter /* The page size is required by the dynamic memory allocator. */ 1897281486Speter init_pagesizes(aux_info); 1898281486Speter#endif 1899281486Speter 190039306Sjdp /* 190139306Sjdp * Conjure up an Obj_Entry structure for the dynamic linker. 190239306Sjdp * 1903194689Sed * The "path" member can't be initialized yet because string constants 1904194705Sed * cannot yet be accessed. Below we will set it correctly. 190539306Sjdp */ 1906124020Sdfr memset(&objtmp, 0, sizeof(objtmp)); 190793610Sjake objtmp.path = NULL; 190893610Sjake objtmp.rtld = true; 190993610Sjake objtmp.mapbase = mapbase; 191045501Sjdp#ifdef PIC 191193610Sjake objtmp.relocbase = mapbase; 191238816Sdfr#endif 1913130661Stmm if (RTLD_IS_DYNAMIC()) { 191493610Sjake objtmp.dynamic = rtld_dynamic(&objtmp); 1915238471Skib digest_dynamic1(&objtmp, 1, &dyn_rpath, &dyn_soname, &dyn_runpath); 191693610Sjake assert(objtmp.needed == NULL); 1917177924Simp#if !defined(__mips__) 1918218025Spluknet /* MIPS has a bogus DT_TEXTREL. */ 191993610Sjake assert(!objtmp.textrel); 1920177924Simp#endif 192134192Sjdp 192245501Sjdp /* 192345501Sjdp * Temporarily put the dynamic linker entry into the object list, so 192445501Sjdp * that symbols can be found. 192545501Sjdp */ 192634192Sjdp 1927233231Skib relocate_objects(&objtmp, true, &objtmp, 0, NULL); 192845501Sjdp } 1929304455Skib ehdr = (Elf_Ehdr *)mapbase; 1930304455Skib objtmp.phdr = (Elf_Phdr *)((char *)mapbase + ehdr->e_phoff); 1931304455Skib objtmp.phsize = ehdr->e_phnum * sizeof(objtmp.phdr[0]); 193234192Sjdp 193393610Sjake /* Initialize the object list. */ 1934296727Skib TAILQ_INIT(&obj_list); 193535529Sdfr 193693610Sjake /* Now that non-local variables can be accesses, copy out obj_rtld. */ 193793610Sjake memcpy(&obj_rtld, &objtmp, sizeof(obj_rtld)); 193893610Sjake 1939281486Speter#ifndef RTLD_INIT_PAGESIZES_EARLY 1940281452Skib /* The page size is required by the dynamic memory allocator. */ 1941281452Skib init_pagesizes(aux_info); 1942281486Speter#endif 1943281452Skib 1944211413Skib if (aux_info[AT_OSRELDATE] != NULL) 1945211413Skib osreldate = aux_info[AT_OSRELDATE]->a_un.a_val; 1946211413Skib 1947238471Skib digest_dynamic2(&obj_rtld, dyn_rpath, dyn_soname, dyn_runpath); 1948211413Skib 194939306Sjdp /* Replace the path with a dynamically allocated copy. */ 195093610Sjake obj_rtld.path = xstrdup(PATH_RTLD); 195139306Sjdp 195235529Sdfr r_debug.r_brk = r_debug_state; 195335529Sdfr r_debug.r_state = RT_CONSISTENT; 195434192Sjdp} 195534192Sjdp 195663870Sjdp/* 1957281452Skib * Retrieve the array of supported page sizes. The kernel provides the page 1958281452Skib * sizes in increasing order. 1959281452Skib */ 1960281452Skibstatic void 1961281452Skibinit_pagesizes(Elf_Auxinfo **aux_info) 1962281452Skib{ 1963281452Skib static size_t psa[MAXPAGESIZES]; 1964281452Skib int mib[2]; 1965281452Skib size_t len, size; 1966281452Skib 1967281452Skib if (aux_info[AT_PAGESIZES] != NULL && aux_info[AT_PAGESIZESLEN] != 1968281452Skib NULL) { 1969281452Skib size = aux_info[AT_PAGESIZESLEN]->a_un.a_val; 1970281452Skib pagesizes = aux_info[AT_PAGESIZES]->a_un.a_ptr; 1971281452Skib } else { 1972281452Skib len = 2; 1973281452Skib if (sysctlnametomib("hw.pagesizes", mib, &len) == 0) 1974281452Skib size = sizeof(psa); 1975281452Skib else { 1976281452Skib /* As a fallback, retrieve the base page size. */ 1977281452Skib size = sizeof(psa[0]); 1978281452Skib if (aux_info[AT_PAGESZ] != NULL) { 1979281452Skib psa[0] = aux_info[AT_PAGESZ]->a_un.a_val; 1980281452Skib goto psa_filled; 1981281452Skib } else { 1982281452Skib mib[0] = CTL_HW; 1983281452Skib mib[1] = HW_PAGESIZE; 1984281452Skib len = 2; 1985281452Skib } 1986281452Skib } 1987281452Skib if (sysctl(mib, len, psa, &size, NULL, 0) == -1) { 1988281452Skib _rtld_error("sysctl for hw.pagesize(s) failed"); 1989282118Semaste rtld_die(); 1990281452Skib } 1991281452Skibpsa_filled: 1992281452Skib pagesizes = psa; 1993281452Skib } 1994281452Skib npagesizes = size / sizeof(pagesizes[0]); 1995281452Skib /* Discard any invalid entries at the end of the array. */ 1996281452Skib while (npagesizes > 0 && pagesizes[npagesizes - 1] == 0) 1997281452Skib npagesizes--; 1998281452Skib} 1999281452Skib 2000281452Skib/* 200163870Sjdp * Add the init functions from a needed object list (and its recursive 200263870Sjdp * needed objects) to "list". This is not used directly; it is a helper 200363870Sjdp * function for initlist_add_objects(). The write lock must be held 200463870Sjdp * when this function is called. 200563870Sjdp */ 200663870Sjdpstatic void 200763870Sjdpinitlist_add_neededs(Needed_Entry *needed, Objlist *list) 200863870Sjdp{ 200963870Sjdp /* Recursively process the successor needed objects. */ 201063870Sjdp if (needed->next != NULL) 201163870Sjdp initlist_add_neededs(needed->next, list); 201263870Sjdp 201363870Sjdp /* Process the current needed object. */ 201463870Sjdp if (needed->obj != NULL) 2015296727Skib initlist_add_objects(needed->obj, needed->obj, list); 201663870Sjdp} 201763870Sjdp 201863870Sjdp/* 201963870Sjdp * Scan all of the DAGs rooted in the range of objects from "obj" to 202063870Sjdp * "tail" and add their init functions to "list". This recurses over 202163870Sjdp * the DAGs and ensure the proper init ordering such that each object's 202263870Sjdp * needed libraries are initialized before the object itself. At the 202363870Sjdp * same time, this function adds the objects to the global finalization 202463870Sjdp * list "list_fini" in the opposite order. The write lock must be 202563870Sjdp * held when this function is called. 202663870Sjdp */ 202763870Sjdpstatic void 2028296727Skibinitlist_add_objects(Obj_Entry *obj, Obj_Entry *tail, Objlist *list) 202963870Sjdp{ 2030296727Skib Obj_Entry *nobj; 2031233231Skib 2032194531Skan if (obj->init_scanned || obj->init_done) 203363870Sjdp return; 2034194531Skan obj->init_scanned = true; 203563870Sjdp 203663870Sjdp /* Recursively process the successor objects. */ 2037296727Skib nobj = globallist_next(obj); 2038296727Skib if (nobj != NULL && obj != tail) 2039296727Skib initlist_add_objects(nobj, tail, list); 204063870Sjdp 204163870Sjdp /* Recursively process the needed objects. */ 204263870Sjdp if (obj->needed != NULL) 204363870Sjdp initlist_add_neededs(obj->needed, list); 2044233231Skib if (obj->needed_filtees != NULL) 2045233231Skib initlist_add_neededs(obj->needed_filtees, list); 2046233231Skib if (obj->needed_aux_filtees != NULL) 2047233231Skib initlist_add_neededs(obj->needed_aux_filtees, list); 204863870Sjdp 204963870Sjdp /* Add the object to the init list. */ 2050232831Skib if (obj->preinit_array != (Elf_Addr)NULL || obj->init != (Elf_Addr)NULL || 2051232831Skib obj->init_array != (Elf_Addr)NULL) 205263870Sjdp objlist_push_tail(list, obj); 205363870Sjdp 205463870Sjdp /* Add the object to the global fini list in the reverse order. */ 2055232831Skib if ((obj->fini != (Elf_Addr)NULL || obj->fini_array != (Elf_Addr)NULL) 2056232831Skib && !obj->on_fini_list) { 205763870Sjdp objlist_push_head(&list_fini, obj); 2058194531Skan obj->on_fini_list = true; 2059194531Skan } 206063870Sjdp} 206163870Sjdp 206285004Sdfr#ifndef FPTR_TARGET 206385004Sdfr#define FPTR_TARGET(f) ((Elf_Addr) (f)) 206485004Sdfr#endif 206585004Sdfr 2066216695Skibstatic void 2067216695Skibfree_needed_filtees(Needed_Entry *n) 2068216695Skib{ 2069216695Skib Needed_Entry *needed, *needed1; 2070216695Skib 2071216695Skib for (needed = n; needed != NULL; needed = needed->next) { 2072216695Skib if (needed->obj != NULL) { 2073216695Skib dlclose(needed->obj); 2074216695Skib needed->obj = NULL; 2075216695Skib } 2076216695Skib } 2077216695Skib for (needed = n; needed != NULL; needed = needed1) { 2078216695Skib needed1 = needed->next; 2079216695Skib free(needed); 2080216695Skib } 2081216695Skib} 2082216695Skib 2083216695Skibstatic void 2084216695Skibunload_filtees(Obj_Entry *obj) 2085216695Skib{ 2086216695Skib 2087216695Skib free_needed_filtees(obj->needed_filtees); 2088216695Skib obj->needed_filtees = NULL; 2089216695Skib free_needed_filtees(obj->needed_aux_filtees); 2090216695Skib obj->needed_aux_filtees = NULL; 2091216695Skib obj->filtees_loaded = false; 2092216695Skib} 2093216695Skib 2094216695Skibstatic void 2095234170Skibload_filtee1(Obj_Entry *obj, Needed_Entry *needed, int flags, 2096234170Skib RtldLockState *lockstate) 2097216695Skib{ 2098216695Skib 2099216695Skib for (; needed != NULL; needed = needed->next) { 2100229768Skib needed->obj = dlopen_object(obj->strtab + needed->name, -1, obj, 2101216695Skib flags, ((ld_loadfltr || obj->z_loadfltr) ? RTLD_NOW : RTLD_LAZY) | 2102234170Skib RTLD_LOCAL, lockstate); 2103216695Skib } 2104216695Skib} 2105216695Skib 2106216695Skibstatic void 2107216695Skibload_filtees(Obj_Entry *obj, int flags, RtldLockState *lockstate) 2108216695Skib{ 2109216695Skib 2110216695Skib lock_restart_for_upgrade(lockstate); 2111216695Skib if (!obj->filtees_loaded) { 2112234170Skib load_filtee1(obj, obj->needed_filtees, flags, lockstate); 2113234170Skib load_filtee1(obj, obj->needed_aux_filtees, flags, lockstate); 2114216695Skib obj->filtees_loaded = true; 2115216695Skib } 2116216695Skib} 2117216695Skib 2118216695Skibstatic int 2119216695Skibprocess_needed(Obj_Entry *obj, Needed_Entry *needed, int flags) 2120216695Skib{ 2121216695Skib Obj_Entry *obj1; 2122216695Skib 2123216695Skib for (; needed != NULL; needed = needed->next) { 2124229768Skib obj1 = needed->obj = load_object(obj->strtab + needed->name, -1, obj, 2125216695Skib flags & ~RTLD_LO_NOLOAD); 2126216695Skib if (obj1 == NULL && !ld_tracing && (flags & RTLD_LO_FILTEES) == 0) 2127216695Skib return (-1); 2128216695Skib } 2129216695Skib return (0); 2130216695Skib} 2131216695Skib 213234192Sjdp/* 213334192Sjdp * Given a shared object, traverse its list of needed objects, and load 213434192Sjdp * each of them. Returns 0 on success. Generates an error message and 213534192Sjdp * returns -1 on failure. 213634192Sjdp */ 213734192Sjdpstatic int 2138199829Skibload_needed_objects(Obj_Entry *first, int flags) 213934192Sjdp{ 2140216695Skib Obj_Entry *obj; 214134192Sjdp 2142304454Skib for (obj = first; obj != NULL; obj = TAILQ_NEXT(obj, next)) { 2143296727Skib if (obj->marker) 2144296727Skib continue; 2145216695Skib if (process_needed(obj, obj->needed, flags) == -1) 2146216695Skib return (-1); 214734192Sjdp } 2148216695Skib return (0); 214934192Sjdp} 215034192Sjdp 215139551Sjdpstatic int 215239551Sjdpload_preload_objects(void) 215339551Sjdp{ 215439551Sjdp char *p = ld_preload; 2155256101Skib Obj_Entry *obj; 215656405Sjdp static const char delim[] = " \t:;"; 215739551Sjdp 215839551Sjdp if (p == NULL) 2159126643Smarkm return 0; 216039551Sjdp 216156405Sjdp p += strspn(p, delim); 216239551Sjdp while (*p != '\0') { 216356405Sjdp size_t len = strcspn(p, delim); 216439551Sjdp char savech; 216539551Sjdp 216639551Sjdp savech = p[len]; 216739551Sjdp p[len] = '\0'; 2168256101Skib obj = load_object(p, -1, NULL, 0); 2169256101Skib if (obj == NULL) 217039551Sjdp return -1; /* XXX - cleanup */ 2171256101Skib obj->z_interpose = true; 217239551Sjdp p[len] = savech; 217339551Sjdp p += len; 217456405Sjdp p += strspn(p, delim); 217539551Sjdp } 2176165916Sjhb LD_UTRACE(UTRACE_PRELOAD_FINISHED, NULL, NULL, 0, 0, NULL); 217739551Sjdp return 0; 217839551Sjdp} 217939551Sjdp 2180229768Skibstatic const char * 2181229768Skibprintable_path(const char *path) 2182229768Skib{ 2183229768Skib 2184229768Skib return (path == NULL ? "<unknown>" : path); 2185229768Skib} 2186229768Skib 218734192Sjdp/* 2188229768Skib * Load a shared object into memory, if it is not already loaded. The 2189229768Skib * object may be specified by name or by user-supplied file descriptor 2190229768Skib * fd_u. In the later case, the fd_u descriptor is not closed, but its 2191229768Skib * duplicate is. 219234192Sjdp * 219334192Sjdp * Returns a pointer to the Obj_Entry for the object. Returns NULL 219434192Sjdp * on failure. 219534192Sjdp */ 219634192Sjdpstatic Obj_Entry * 2197229768Skibload_object(const char *name, int fd_u, const Obj_Entry *refobj, int flags) 219834192Sjdp{ 219934192Sjdp Obj_Entry *obj; 2200229768Skib int fd; 220150609Sjdp struct stat sb; 2202153515Skan char *path; 220334192Sjdp 2204229768Skib if (name != NULL) { 2205296727Skib TAILQ_FOREACH(obj, &obj_list, next) { 2206296727Skib if (obj->marker) 2207296727Skib continue; 2208229768Skib if (object_match_name(obj, name)) 2209229768Skib return (obj); 2210229768Skib } 221134192Sjdp 2212229768Skib path = find_library(name, refobj); 2213229768Skib if (path == NULL) 2214229768Skib return (NULL); 2215229768Skib } else 2216229768Skib path = NULL; 2217153515Skan 221850609Sjdp /* 2219229768Skib * If we didn't find a match by pathname, or the name is not 2220229768Skib * supplied, open the file and check again by device and inode. 2221229768Skib * This avoids false mismatches caused by multiple links or ".." 2222229768Skib * in pathnames. 222350609Sjdp * 222450609Sjdp * To avoid a race, we open the file and use fstat() rather than 222550609Sjdp * using stat(). 222650609Sjdp */ 2227229768Skib fd = -1; 2228229768Skib if (fd_u == -1) { 2229242587Sjilles if ((fd = open(path, O_RDONLY | O_CLOEXEC)) == -1) { 2230229768Skib _rtld_error("Cannot open \"%s\"", path); 2231229768Skib free(path); 2232229768Skib return (NULL); 2233229768Skib } 2234229768Skib } else { 2235242587Sjilles fd = fcntl(fd_u, F_DUPFD_CLOEXEC, 0); 2236229768Skib if (fd == -1) { 2237229768Skib _rtld_error("Cannot dup fd"); 2238229768Skib free(path); 2239229768Skib return (NULL); 2240229768Skib } 2241153515Skan } 2242153515Skan if (fstat(fd, &sb) == -1) { 2243229768Skib _rtld_error("Cannot fstat \"%s\"", printable_path(path)); 2244153515Skan close(fd); 2245153515Skan free(path); 2246153515Skan return NULL; 2247153515Skan } 2248296727Skib TAILQ_FOREACH(obj, &obj_list, next) { 2249296727Skib if (obj->marker) 2250296727Skib continue; 2251220004Savg if (obj->ino == sb.st_ino && obj->dev == sb.st_dev) 2252153515Skan break; 2253296727Skib } 2254229768Skib if (obj != NULL && name != NULL) { 2255153515Skan object_add_name(obj, name); 2256153515Skan free(path); 2257153515Skan close(fd); 2258153515Skan return obj; 2259153515Skan } 2260208763Skan if (flags & RTLD_LO_NOLOAD) { 2261208763Skan free(path); 2262227660Skib close(fd); 2263195745Skib return (NULL); 2264208763Skan } 226550609Sjdp 2266153515Skan /* First use of this object, so we must map it in */ 2267199829Skib obj = do_load_object(fd, name, path, &sb, flags); 2268153515Skan if (obj == NULL) 2269153515Skan free(path); 2270153515Skan close(fd); 2271153515Skan 2272153515Skan return obj; 2273153515Skan} 2274153515Skan 2275153515Skanstatic Obj_Entry * 2276199829Skibdo_load_object(int fd, const char *name, char *path, struct stat *sbp, 2277199829Skib int flags) 2278153515Skan{ 2279153515Skan Obj_Entry *obj; 2280153515Skan struct statfs fs; 2281153515Skan 2282153515Skan /* 2283153515Skan * but first, make sure that environment variables haven't been 2284153515Skan * used to circumvent the noexec flag on a filesystem. 2285153515Skan */ 2286153515Skan if (dangerous_ld_env) { 2287153515Skan if (fstatfs(fd, &fs) != 0) { 2288229768Skib _rtld_error("Cannot fstatfs \"%s\"", printable_path(path)); 2289229768Skib return NULL; 2290144062Scperciva } 2291153515Skan if (fs.f_flags & MNT_NOEXEC) { 2292153515Skan _rtld_error("Cannot execute objects on %s\n", fs.f_mntonname); 229334192Sjdp return NULL; 229434192Sjdp } 2295153515Skan } 2296229768Skib dbg("loading \"%s\"", printable_path(path)); 2297229768Skib obj = map_object(fd, printable_path(path), sbp); 2298153515Skan if (obj == NULL) 2299153515Skan return NULL; 230034192Sjdp 2301229768Skib /* 2302229768Skib * If DT_SONAME is present in the object, digest_dynamic2 already 2303229768Skib * added it to the object names. 2304229768Skib */ 2305229768Skib if (name != NULL) 2306229768Skib object_add_name(obj, name); 2307153515Skan obj->path = path; 2308153515Skan digest_dynamic(obj, 0); 2309234841Skib dbg("%s valid_hash_sysv %d valid_hash_gnu %d dynsymcount %d", obj->path, 2310234841Skib obj->valid_hash_sysv, obj->valid_hash_gnu, obj->dynsymcount); 2311199877Skib if (obj->z_noopen && (flags & (RTLD_LO_DLOPEN | RTLD_LO_TRACE)) == 2312199877Skib RTLD_LO_DLOPEN) { 2313199829Skib dbg("refusing to load non-loadable \"%s\"", obj->path); 2314199877Skib _rtld_error("Cannot dlopen non-loadable %s", obj->path); 2315199829Skib munmap(obj->mapbase, obj->mapsize); 2316199829Skib obj_free(obj); 2317199829Skib return (NULL); 2318199829Skib } 231934192Sjdp 2320276908Skib obj->dlopened = (flags & RTLD_LO_DLOPEN) != 0; 2321296727Skib TAILQ_INSERT_TAIL(&obj_list, obj, next); 2322153515Skan obj_count++; 2323168312Skan obj_loads++; 2324153515Skan linkmap_add(obj); /* for GDB & dlinfo() */ 2325217153Skib max_stack_flags |= obj->stack_flags; 232634192Sjdp 2327153515Skan dbg(" %p .. %p: %s", obj->mapbase, 2328153515Skan obj->mapbase + obj->mapsize - 1, obj->path); 2329153515Skan if (obj->textrel) 2330153515Skan dbg(" WARNING: %s has impure text", obj->path); 2331165916Sjhb LD_UTRACE(UTRACE_LOAD_OBJECT, obj, obj->mapbase, obj->mapsize, 0, 2332165916Sjhb obj->path); 233334192Sjdp 233434192Sjdp return obj; 233534192Sjdp} 233634192Sjdp 233734192Sjdpstatic Obj_Entry * 233834192Sjdpobj_from_addr(const void *addr) 233934192Sjdp{ 234034192Sjdp Obj_Entry *obj; 234134192Sjdp 2342296727Skib TAILQ_FOREACH(obj, &obj_list, next) { 2343296727Skib if (obj->marker) 2344296727Skib continue; 234534192Sjdp if (addr < (void *) obj->mapbase) 234634192Sjdp continue; 2347126236Skan if (addr < (void *) (obj->mapbase + obj->mapsize)) 234834192Sjdp return obj; 234934192Sjdp } 235034192Sjdp return NULL; 235134192Sjdp} 235234192Sjdp 2353232831Skibstatic void 2354232831Skibpreinit_main(void) 2355232831Skib{ 2356232831Skib Elf_Addr *preinit_addr; 2357232831Skib int index; 2358232831Skib 2359232831Skib preinit_addr = (Elf_Addr *)obj_main->preinit_array; 2360232859Sdim if (preinit_addr == NULL) 2361232831Skib return; 2362232831Skib 2363232831Skib for (index = 0; index < obj_main->preinit_array_num; index++) { 2364232831Skib if (preinit_addr[index] != 0 && preinit_addr[index] != 1) { 2365232831Skib dbg("calling preinit function for %s at %p", obj_main->path, 2366232831Skib (void *)preinit_addr[index]); 2367232831Skib LD_UTRACE(UTRACE_INIT_CALL, obj_main, (void *)preinit_addr[index], 2368232831Skib 0, 0, obj_main->path); 2369232831Skib call_init_pointer(obj_main, preinit_addr[index]); 2370232831Skib } 2371232831Skib } 2372232831Skib} 2373232831Skib 237463870Sjdp/* 237563870Sjdp * Call the finalization functions for each of the objects in "list" 2376216489Sjh * belonging to the DAG of "root" and referenced once. If NULL "root" 2377216489Sjh * is specified, every finalization function will be called regardless 2378216489Sjh * of the reference count and the list elements won't be freed. All of 2379216489Sjh * the objects are expected to have non-NULL fini functions. 238063870Sjdp */ 238150608Sjdpstatic void 2382216695Skibobjlist_call_fini(Objlist *list, Obj_Entry *root, RtldLockState *lockstate) 238350608Sjdp{ 2384216489Sjh Objlist_Entry *elm; 238570677Sjdp char *saved_msg; 2386232831Skib Elf_Addr *fini_addr; 2387232831Skib int index; 238850608Sjdp 2389216489Sjh assert(root == NULL || root->refcount == 1); 2390216489Sjh 239170677Sjdp /* 239270677Sjdp * Preserve the current error message since a fini function might 239370677Sjdp * call into the dynamic linker and overwrite it. 239470677Sjdp */ 239570677Sjdp saved_msg = errmsg_save(); 2396216489Sjh do { 2397216489Sjh STAILQ_FOREACH(elm, list, link) { 2398216489Sjh if (root != NULL && (elm->obj->refcount != 1 || 2399216489Sjh objlist_find(&root->dagmembers, elm->obj) == NULL)) 2400216489Sjh continue; 2401194531Skan /* Remove object from fini list to prevent recursive invocation. */ 2402194531Skan STAILQ_REMOVE(list, elm, Struct_Objlist_Entry, link); 2403216489Sjh /* 2404216489Sjh * XXX: If a dlopen() call references an object while the 2405216489Sjh * fini function is in progress, we might end up trying to 2406216489Sjh * unload the referenced object in dlclose() or the object 2407216489Sjh * won't be unloaded although its fini function has been 2408216489Sjh * called. 2409216489Sjh */ 2410216695Skib lock_release(rtld_bind_lock, lockstate); 2411232831Skib 2412232831Skib /* 2413232831Skib * It is legal to have both DT_FINI and DT_FINI_ARRAY defined. 2414232831Skib * When this happens, DT_FINI_ARRAY is processed first. 2415232831Skib */ 2416232831Skib fini_addr = (Elf_Addr *)elm->obj->fini_array; 2417232831Skib if (fini_addr != NULL && elm->obj->fini_array_num > 0) { 2418232831Skib for (index = elm->obj->fini_array_num - 1; index >= 0; 2419232831Skib index--) { 2420232831Skib if (fini_addr[index] != 0 && fini_addr[index] != 1) { 2421232831Skib dbg("calling fini function for %s at %p", 2422232831Skib elm->obj->path, (void *)fini_addr[index]); 2423232831Skib LD_UTRACE(UTRACE_FINI_CALL, elm->obj, 2424232831Skib (void *)fini_addr[index], 0, 0, elm->obj->path); 2425232831Skib call_initfini_pointer(elm->obj, fini_addr[index]); 2426232831Skib } 2427232831Skib } 2428232831Skib } 2429232831Skib if (elm->obj->fini != (Elf_Addr)NULL) { 2430232831Skib dbg("calling fini function for %s at %p", elm->obj->path, 2431232831Skib (void *)elm->obj->fini); 2432232831Skib LD_UTRACE(UTRACE_FINI_CALL, elm->obj, (void *)elm->obj->fini, 2433232831Skib 0, 0, elm->obj->path); 2434232831Skib call_initfini_pointer(elm->obj, elm->obj->fini); 2435232831Skib } 2436216695Skib wlock_acquire(rtld_bind_lock, lockstate); 2437194531Skan /* No need to free anything if process is going down. */ 2438216489Sjh if (root != NULL) 2439194531Skan free(elm); 2440216489Sjh /* 2441216489Sjh * We must restart the list traversal after every fini call 2442216489Sjh * because a dlclose() call from the fini function or from 2443216489Sjh * another thread might have modified the reference counts. 2444216489Sjh */ 2445216489Sjh break; 244663870Sjdp } 2447216489Sjh } while (elm != NULL); 244870677Sjdp errmsg_restore(saved_msg); 244950608Sjdp} 245050608Sjdp 245163870Sjdp/* 245263870Sjdp * Call the initialization functions for each of the objects in 245363870Sjdp * "list". All of the objects are expected to have non-NULL init 245463870Sjdp * functions. 245563870Sjdp */ 245663870Sjdpstatic void 2457216695Skibobjlist_call_init(Objlist *list, RtldLockState *lockstate) 245863870Sjdp{ 245963870Sjdp Objlist_Entry *elm; 2460194531Skan Obj_Entry *obj; 246170677Sjdp char *saved_msg; 2462232831Skib Elf_Addr *init_addr; 2463232831Skib int index; 246463870Sjdp 246570677Sjdp /* 2466194531Skan * Clean init_scanned flag so that objects can be rechecked and 2467194531Skan * possibly initialized earlier if any of vectors called below 2468194531Skan * cause the change by using dlopen. 2469194531Skan */ 2470296727Skib TAILQ_FOREACH(obj, &obj_list, next) { 2471296727Skib if (obj->marker) 2472296727Skib continue; 2473194531Skan obj->init_scanned = false; 2474296727Skib } 2475194531Skan 2476194531Skan /* 247770677Sjdp * Preserve the current error message since an init function might 247870677Sjdp * call into the dynamic linker and overwrite it. 247970677Sjdp */ 248070677Sjdp saved_msg = errmsg_save(); 248163870Sjdp STAILQ_FOREACH(elm, list, link) { 2482194531Skan if (elm->obj->init_done) /* Initialized early. */ 2483194531Skan continue; 2484194531Skan /* 2485194531Skan * Race: other thread might try to use this object before current 2486310238Skib * one completes the initialization. Not much can be done here 2487194531Skan * without better locking. 2488194531Skan */ 2489194531Skan elm->obj->init_done = true; 2490216695Skib lock_release(rtld_bind_lock, lockstate); 2491232831Skib 2492232831Skib /* 2493232831Skib * It is legal to have both DT_INIT and DT_INIT_ARRAY defined. 2494232831Skib * When this happens, DT_INIT is processed first. 2495232831Skib */ 2496232831Skib if (elm->obj->init != (Elf_Addr)NULL) { 2497232831Skib dbg("calling init function for %s at %p", elm->obj->path, 2498232831Skib (void *)elm->obj->init); 2499232831Skib LD_UTRACE(UTRACE_INIT_CALL, elm->obj, (void *)elm->obj->init, 2500232831Skib 0, 0, elm->obj->path); 2501232831Skib call_initfini_pointer(elm->obj, elm->obj->init); 2502232831Skib } 2503232831Skib init_addr = (Elf_Addr *)elm->obj->init_array; 2504232859Sdim if (init_addr != NULL) { 2505232831Skib for (index = 0; index < elm->obj->init_array_num; index++) { 2506232831Skib if (init_addr[index] != 0 && init_addr[index] != 1) { 2507232831Skib dbg("calling init function for %s at %p", elm->obj->path, 2508232831Skib (void *)init_addr[index]); 2509232831Skib LD_UTRACE(UTRACE_INIT_CALL, elm->obj, 2510232831Skib (void *)init_addr[index], 0, 0, elm->obj->path); 2511232831Skib call_init_pointer(elm->obj, init_addr[index]); 2512232831Skib } 2513232831Skib } 2514232831Skib } 2515216695Skib wlock_acquire(rtld_bind_lock, lockstate); 251663870Sjdp } 251770677Sjdp errmsg_restore(saved_msg); 251863870Sjdp} 251963870Sjdp 252063870Sjdpstatic void 252163870Sjdpobjlist_clear(Objlist *list) 252263870Sjdp{ 252363870Sjdp Objlist_Entry *elm; 252463870Sjdp 252563870Sjdp while (!STAILQ_EMPTY(list)) { 252663870Sjdp elm = STAILQ_FIRST(list); 252763870Sjdp STAILQ_REMOVE_HEAD(list, link); 252863870Sjdp free(elm); 252963870Sjdp } 253063870Sjdp} 253163870Sjdp 253250608Sjdpstatic Objlist_Entry * 253350608Sjdpobjlist_find(Objlist *list, const Obj_Entry *obj) 253450608Sjdp{ 253550608Sjdp Objlist_Entry *elm; 253650608Sjdp 253750608Sjdp STAILQ_FOREACH(elm, list, link) 253850608Sjdp if (elm->obj == obj) 253950608Sjdp return elm; 254050608Sjdp return NULL; 254150608Sjdp} 254250608Sjdp 254350608Sjdpstatic void 254463870Sjdpobjlist_init(Objlist *list) 254563870Sjdp{ 254663870Sjdp STAILQ_INIT(list); 254763870Sjdp} 254863870Sjdp 254963870Sjdpstatic void 255063870Sjdpobjlist_push_head(Objlist *list, Obj_Entry *obj) 255163870Sjdp{ 255263870Sjdp Objlist_Entry *elm; 255363870Sjdp 255463870Sjdp elm = NEW(Objlist_Entry); 255563870Sjdp elm->obj = obj; 255663870Sjdp STAILQ_INSERT_HEAD(list, elm, link); 255763870Sjdp} 255863870Sjdp 255963870Sjdpstatic void 256063870Sjdpobjlist_push_tail(Objlist *list, Obj_Entry *obj) 256163870Sjdp{ 256263870Sjdp Objlist_Entry *elm; 256363870Sjdp 256463870Sjdp elm = NEW(Objlist_Entry); 256563870Sjdp elm->obj = obj; 256663870Sjdp STAILQ_INSERT_TAIL(list, elm, link); 256763870Sjdp} 256863870Sjdp 256963870Sjdpstatic void 2570256101Skibobjlist_put_after(Objlist *list, Obj_Entry *listobj, Obj_Entry *obj) 2571256101Skib{ 2572256101Skib Objlist_Entry *elm, *listelm; 2573256101Skib 2574256101Skib STAILQ_FOREACH(listelm, list, link) { 2575256101Skib if (listelm->obj == listobj) 2576256101Skib break; 2577256101Skib } 2578256101Skib elm = NEW(Objlist_Entry); 2579256101Skib elm->obj = obj; 2580256101Skib if (listelm != NULL) 2581256101Skib STAILQ_INSERT_AFTER(list, listelm, elm, link); 2582256101Skib else 2583256101Skib STAILQ_INSERT_TAIL(list, elm, link); 2584256101Skib} 2585256101Skib 2586256101Skibstatic void 258750608Sjdpobjlist_remove(Objlist *list, Obj_Entry *obj) 258850608Sjdp{ 258950608Sjdp Objlist_Entry *elm; 259050608Sjdp 259150608Sjdp if ((elm = objlist_find(list, obj)) != NULL) { 259260938Sjake STAILQ_REMOVE(list, elm, Struct_Objlist_Entry, link); 259350608Sjdp free(elm); 259450608Sjdp } 259550608Sjdp} 259650608Sjdp 259734192Sjdp/* 2598237659Skib * Relocate dag rooted in the specified object. 2599237659Skib * Returns 0 on success, or -1 on failure. 260034192Sjdp */ 2601237659Skib 260234192Sjdpstatic int 2603237659Skibrelocate_object_dag(Obj_Entry *root, bool bind_now, Obj_Entry *rtldobj, 2604233231Skib int flags, RtldLockState *lockstate) 260534192Sjdp{ 2606237659Skib Objlist_Entry *elm; 2607237659Skib int error; 260834192Sjdp 2609237659Skib error = 0; 2610237659Skib STAILQ_FOREACH(elm, &root->dagmembers, link) { 2611237659Skib error = relocate_object(elm->obj, bind_now, rtldobj, flags, 2612237659Skib lockstate); 2613237659Skib if (error == -1) 2614237659Skib break; 2615237659Skib } 2616237659Skib return (error); 2617237659Skib} 2618237659Skib 2619237659Skib/* 2620296939Skib * Prepare for, or clean after, relocating an object marked with 2621296939Skib * DT_TEXTREL or DF_TEXTREL. Before relocating, all read-only 2622296939Skib * segments are remapped read-write. After relocations are done, the 2623296939Skib * segment's permissions are returned back to the modes specified in 2624296939Skib * the phdrs. If any relocation happened, or always for wired 2625296939Skib * program, COW is triggered. 2626296939Skib */ 2627296939Skibstatic int 2628296939Skibreloc_textrel_prot(Obj_Entry *obj, bool before) 2629296939Skib{ 2630296939Skib const Elf_Phdr *ph; 2631296939Skib void *base; 2632296939Skib size_t l, sz; 2633296939Skib int prot; 2634296939Skib 2635296939Skib for (l = obj->phsize / sizeof(*ph), ph = obj->phdr; l > 0; 2636296939Skib l--, ph++) { 2637296939Skib if (ph->p_type != PT_LOAD || (ph->p_flags & PF_W) != 0) 2638296939Skib continue; 2639296939Skib base = obj->relocbase + trunc_page(ph->p_vaddr); 2640296939Skib sz = round_page(ph->p_vaddr + ph->p_filesz) - 2641296939Skib trunc_page(ph->p_vaddr); 2642296939Skib prot = convert_prot(ph->p_flags) | (before ? PROT_WRITE : 0); 2643296939Skib if (mprotect(base, sz, prot) == -1) { 2644296939Skib _rtld_error("%s: Cannot write-%sable text segment: %s", 2645296939Skib obj->path, before ? "en" : "dis", 2646296939Skib rtld_strerror(errno)); 2647296939Skib return (-1); 2648296939Skib } 2649296939Skib } 2650296939Skib return (0); 2651296939Skib} 2652296939Skib 2653296939Skib/* 2654237659Skib * Relocate single object. 2655237659Skib * Returns 0 on success, or -1 on failure. 2656237659Skib */ 2657237659Skibstatic int 2658237659Skibrelocate_object(Obj_Entry *obj, bool bind_now, Obj_Entry *rtldobj, 2659237659Skib int flags, RtldLockState *lockstate) 2660237659Skib{ 2661237659Skib 2662233231Skib if (obj->relocated) 2663237659Skib return (0); 2664233231Skib obj->relocated = true; 266593610Sjake if (obj != rtldobj) 2666237659Skib dbg("relocating \"%s\"", obj->path); 2667233231Skib 2668234841Skib if (obj->symtab == NULL || obj->strtab == NULL || 2669237659Skib !(obj->valid_hash_sysv || obj->valid_hash_gnu)) { 2670237659Skib _rtld_error("%s: Shared object has no run-time symbol table", 2671237659Skib obj->path); 2672237659Skib return (-1); 267334192Sjdp } 267434192Sjdp 2675296939Skib /* There are relocations to the write-protected text segment. */ 2676296939Skib if (obj->textrel && reloc_textrel_prot(obj, true) != 0) 2677296939Skib return (-1); 267834192Sjdp 2679271469Skib /* Process the non-PLT non-IFUNC relocations. */ 2680233231Skib if (reloc_non_plt(obj, rtldobj, flags, lockstate)) 2681237659Skib return (-1); 268234192Sjdp 2683296939Skib /* Re-protected the text segment. */ 2684296939Skib if (obj->textrel && reloc_textrel_prot(obj, false) != 0) 2685296939Skib return (-1); 268634192Sjdp 2687228435Skib /* Set the special PLT or GOT entries. */ 2688228435Skib init_pltgot(obj); 2689228435Skib 269034192Sjdp /* Process the PLT relocations. */ 269156780Sjdp if (reloc_plt(obj) == -1) 2692237659Skib return (-1); 269356780Sjdp /* Relocate the jump slots if we are doing immediate binding. */ 2694116511Smdodd if (obj->bind_now || bind_now) 2695237659Skib if (reloc_jmpslots(obj, flags, lockstate) == -1) 2696237659Skib return (-1); 269734192Sjdp 2698271469Skib /* 2699271469Skib * Process the non-PLT IFUNC relocations. The relocations are 2700271469Skib * processed in two phases, because IFUNC resolvers may 2701271469Skib * reference other symbols, which must be readily processed 2702271469Skib * before resolvers are called. 2703271469Skib */ 2704271469Skib if (obj->non_plt_gnu_ifunc && 2705271469Skib reloc_non_plt(obj, rtldobj, flags | SYMLOOK_IFUNC, lockstate)) 2706271469Skib return (-1); 2707271469Skib 2708312402Skib if (!obj->mainprog && obj_enforce_relro(obj) == -1) 2709312402Skib return (-1); 2710230784Skib 271134192Sjdp /* 271234192Sjdp * Set up the magic number and version in the Obj_Entry. These 271334192Sjdp * were checked in the crt1.o from the original ElfKit, so we 271434192Sjdp * set them for backward compatibility. 271534192Sjdp */ 271634192Sjdp obj->magic = RTLD_MAGIC; 271734192Sjdp obj->version = RTLD_VERSION; 271834192Sjdp 2719237659Skib return (0); 2720228503Skib} 2721228503Skib 2722228503Skib/* 2723237659Skib * Relocate newly-loaded shared objects. The argument is a pointer to 2724237659Skib * the Obj_Entry for the first such object. All objects from the first 2725237659Skib * to the end of the list of objects are relocated. Returns 0 on success, 2726237659Skib * or -1 on failure. 2727237659Skib */ 2728237659Skibstatic int 2729237659Skibrelocate_objects(Obj_Entry *first, bool bind_now, Obj_Entry *rtldobj, 2730237659Skib int flags, RtldLockState *lockstate) 2731237659Skib{ 2732237659Skib Obj_Entry *obj; 2733237659Skib int error; 2734237659Skib 2735304454Skib for (error = 0, obj = first; obj != NULL; 2736304454Skib obj = TAILQ_NEXT(obj, next)) { 2737296727Skib if (obj->marker) 2738296727Skib continue; 2739237659Skib error = relocate_object(obj, bind_now, rtldobj, flags, 2740237659Skib lockstate); 2741237659Skib if (error == -1) 2742237659Skib break; 2743237659Skib } 2744237659Skib return (error); 2745237659Skib} 2746237659Skib 2747237659Skib/* 2748228503Skib * The handling of R_MACHINE_IRELATIVE relocations and jumpslots 2749228503Skib * referencing STT_GNU_IFUNC symbols is postponed till the other 2750228503Skib * relocations are done. The indirect functions specified as 2751228503Skib * ifunc are allowed to call other symbols, so we need to have 2752228503Skib * objects relocated before asking for resolution from indirects. 2753228503Skib * 2754228503Skib * The R_MACHINE_IRELATIVE slots are resolved in greedy fashion, 2755228503Skib * instead of the usual lazy handling of PLT slots. It is 2756228503Skib * consistent with how GNU does it. 2757228503Skib */ 2758228503Skibstatic int 2759233231Skibresolve_object_ifunc(Obj_Entry *obj, bool bind_now, int flags, 2760233231Skib RtldLockState *lockstate) 2761228503Skib{ 2762228435Skib if (obj->irelative && reloc_iresolve(obj, lockstate) == -1) 2763228503Skib return (-1); 2764228435Skib if ((obj->bind_now || bind_now) && obj->gnu_ifunc && 2765233231Skib reloc_gnu_ifunc(obj, flags, lockstate) == -1) 2766228503Skib return (-1); 2767228503Skib return (0); 276834192Sjdp} 276934192Sjdp 2770228503Skibstatic int 2771233231Skibresolve_objects_ifunc(Obj_Entry *first, bool bind_now, int flags, 2772233231Skib RtldLockState *lockstate) 2773228503Skib{ 2774228503Skib Obj_Entry *obj; 2775228503Skib 2776304454Skib for (obj = first; obj != NULL; obj = TAILQ_NEXT(obj, next)) { 2777296727Skib if (obj->marker) 2778296727Skib continue; 2779233231Skib if (resolve_object_ifunc(obj, bind_now, flags, lockstate) == -1) 2780228503Skib return (-1); 2781228503Skib } 2782228503Skib return (0); 2783228503Skib} 2784228503Skib 2785228503Skibstatic int 2786233231Skibinitlist_objects_ifunc(Objlist *list, bool bind_now, int flags, 2787233231Skib RtldLockState *lockstate) 2788228503Skib{ 2789228503Skib Objlist_Entry *elm; 2790228503Skib 2791228503Skib STAILQ_FOREACH(elm, list, link) { 2792233231Skib if (resolve_object_ifunc(elm->obj, bind_now, flags, 2793233231Skib lockstate) == -1) 2794228503Skib return (-1); 2795228503Skib } 2796228503Skib return (0); 2797228503Skib} 2798228503Skib 279934192Sjdp/* 280034192Sjdp * Cleanup procedure. It will be called (by the atexit mechanism) just 280134192Sjdp * before the process exits. 280234192Sjdp */ 280334192Sjdpstatic void 280434192Sjdprtld_exit(void) 280534192Sjdp{ 2806216695Skib RtldLockState lockstate; 280755687Sjdp 2808216695Skib wlock_acquire(rtld_bind_lock, &lockstate); 280934192Sjdp dbg("rtld_exit()"); 2810216489Sjh objlist_call_fini(&list_fini, NULL, &lockstate); 281163870Sjdp /* No need to remove the items from the list, since we are exiting. */ 2812115444Smdodd if (!libmap_disable) 2813115444Smdodd lm_fini(); 2814216695Skib lock_release(rtld_bind_lock, &lockstate); 281534192Sjdp} 281634192Sjdp 2817255765Sdes/* 2818255765Sdes * Iterate over a search path, translate each element, and invoke the 2819255765Sdes * callback on the result. 2820255765Sdes */ 2821110804Skanstatic void * 2822110804Skanpath_enumerate(const char *path, path_enum_proc callback, void *arg) 282334192Sjdp{ 2824127250Speter const char *trans; 2825110804Skan if (path == NULL) 2826110804Skan return (NULL); 282734192Sjdp 2828110804Skan path += strspn(path, ":;"); 2829110804Skan while (*path != '\0') { 2830110804Skan size_t len; 2831110804Skan char *res; 283234192Sjdp 2833110804Skan len = strcspn(path, ":;"); 2834127250Speter trans = lm_findn(NULL, path, len); 2835127250Speter if (trans) 2836127250Speter res = callback(trans, strlen(trans), arg); 2837127250Speter else 2838255765Sdes res = callback(path, len, arg); 283934192Sjdp 2840110804Skan if (res != NULL) 2841110804Skan return (res); 284234192Sjdp 2843110804Skan path += len; 2844110804Skan path += strspn(path, ":;"); 2845110804Skan } 284634192Sjdp 2847110804Skan return (NULL); 2848110804Skan} 284934192Sjdp 2850110804Skanstruct try_library_args { 2851110804Skan const char *name; 2852110804Skan size_t namelen; 2853110804Skan char *buffer; 2854110804Skan size_t buflen; 2855110804Skan}; 2856110804Skan 2857110804Skanstatic void * 2858110804Skantry_library_path(const char *dir, size_t dirlen, void *param) 2859110804Skan{ 2860110804Skan struct try_library_args *arg; 2861110804Skan 2862110804Skan arg = param; 2863110804Skan if (*dir == '/' || trust) { 2864110804Skan char *pathname; 2865110804Skan 2866110804Skan if (dirlen + 1 + arg->namelen + 1 > arg->buflen) 2867110804Skan return (NULL); 2868110804Skan 2869110804Skan pathname = arg->buffer; 2870110804Skan strncpy(pathname, dir, dirlen); 2871110804Skan pathname[dirlen] = '/'; 2872110804Skan strcpy(pathname + dirlen + 1, arg->name); 2873110804Skan 2874110804Skan dbg(" Trying \"%s\"", pathname); 2875110804Skan if (access(pathname, F_OK) == 0) { /* We found it */ 2876110804Skan pathname = xmalloc(dirlen + 1 + arg->namelen + 1); 2877110804Skan strcpy(pathname, arg->buffer); 2878110804Skan return (pathname); 287934192Sjdp } 288034192Sjdp } 2881110804Skan return (NULL); 2882110804Skan} 288334192Sjdp 2884110804Skanstatic char * 2885110804Skansearch_library_path(const char *name, const char *path) 2886110804Skan{ 2887110804Skan char *p; 2888110804Skan struct try_library_args arg; 2889110804Skan 2890110804Skan if (path == NULL) 2891110804Skan return NULL; 2892110804Skan 2893110804Skan arg.name = name; 2894110804Skan arg.namelen = strlen(name); 2895110804Skan arg.buffer = xmalloc(PATH_MAX); 2896110804Skan arg.buflen = PATH_MAX; 2897110804Skan 2898110804Skan p = path_enumerate(path, try_library_path, &arg); 2899110804Skan 2900110804Skan free(arg.buffer); 2901110804Skan 2902110804Skan return (p); 290334192Sjdp} 290434192Sjdp 290534192Sjdpint 290634192Sjdpdlclose(void *handle) 290734192Sjdp{ 290855122Sjdp Obj_Entry *root; 2909216695Skib RtldLockState lockstate; 291034192Sjdp 2911216695Skib wlock_acquire(rtld_bind_lock, &lockstate); 291255122Sjdp root = dlcheck(handle); 291355122Sjdp if (root == NULL) { 2914216695Skib lock_release(rtld_bind_lock, &lockstate); 291534192Sjdp return -1; 291655122Sjdp } 2917165916Sjhb LD_UTRACE(UTRACE_DLCLOSE_START, handle, NULL, 0, root->dl_refcount, 2918165916Sjhb root->path); 291934192Sjdp 292055687Sjdp /* Unreference the object and its dependencies. */ 292134192Sjdp root->dl_refcount--; 2922114826Skan 2923216489Sjh if (root->refcount == 1) { 292455687Sjdp /* 2925216489Sjh * The object will be no longer referenced, so we must unload it. 2926182698Skan * First, call the fini functions. 292755687Sjdp */ 2928216489Sjh objlist_call_fini(&list_fini, root, &lockstate); 292955687Sjdp 2930216489Sjh unref_dag(root); 2931216489Sjh 293255687Sjdp /* Finish cleaning up the newly-unreferenced objects. */ 293365109Sjwd GDB_STATE(RT_DELETE,&root->linkmap); 293455687Sjdp unload_object(root); 293565109Sjwd GDB_STATE(RT_CONSISTENT,NULL); 2936216489Sjh } else 2937216489Sjh unref_dag(root); 2938216489Sjh 2939165916Sjhb LD_UTRACE(UTRACE_DLCLOSE_STOP, handle, NULL, 0, 0, NULL); 2940216695Skib lock_release(rtld_bind_lock, &lockstate); 294134192Sjdp return 0; 294234192Sjdp} 294334192Sjdp 2944205606Sgahrchar * 294534192Sjdpdlerror(void) 294634192Sjdp{ 294734192Sjdp char *msg = error_message; 294834192Sjdp error_message = NULL; 294934192Sjdp return msg; 295034192Sjdp} 295134192Sjdp 295262801Sjdp/* 295362801Sjdp * This function is deprecated and has no effect. 295462801Sjdp */ 295555122Sjdpvoid 295655122Sjdpdllockinit(void *context, 295755122Sjdp void *(*lock_create)(void *context), 295855122Sjdp void (*rlock_acquire)(void *lock), 295955122Sjdp void (*wlock_acquire)(void *lock), 296055122Sjdp void (*lock_release)(void *lock), 296155122Sjdp void (*lock_destroy)(void *lock), 296255122Sjdp void (*context_destroy)(void *context)) 296355122Sjdp{ 296462801Sjdp static void *cur_context; 296562801Sjdp static void (*cur_context_destroy)(void *); 296656780Sjdp 296762801Sjdp /* Just destroy the context from the previous call, if necessary. */ 296862801Sjdp if (cur_context_destroy != NULL) 296962801Sjdp cur_context_destroy(cur_context); 297062801Sjdp cur_context = context; 297162801Sjdp cur_context_destroy = context_destroy; 297255122Sjdp} 297355122Sjdp 297434192Sjdpvoid * 297534192Sjdpdlopen(const char *name, int mode) 297634192Sjdp{ 2977229768Skib 2978229768Skib return (rtld_dlopen(name, -1, mode)); 2979229768Skib} 2980229768Skib 2981229768Skibvoid * 2982229768Skibfdlopen(int fd, int mode) 2983229768Skib{ 2984229768Skib 2985229768Skib return (rtld_dlopen(NULL, fd, mode)); 2986229768Skib} 2987229768Skib 2988229768Skibstatic void * 2989229768Skibrtld_dlopen(const char *name, int fd, int mode) 2990229768Skib{ 2991217223Skib RtldLockState lockstate; 2992216695Skib int lo_flags; 299334192Sjdp 2994165916Sjhb LD_UTRACE(UTRACE_DLOPEN_START, NULL, NULL, 0, mode, name); 299590172Ssobomax ld_tracing = (mode & RTLD_TRACE) == 0 ? NULL : "1"; 2996217223Skib if (ld_tracing != NULL) { 2997217223Skib rlock_acquire(rtld_bind_lock, &lockstate); 2998218476Skib if (sigsetjmp(lockstate.env, 0) != 0) 2999217223Skib lock_upgrade(rtld_bind_lock, &lockstate); 3000217223Skib environ = (char **)*get_program_var_addr("environ", &lockstate); 3001217223Skib lock_release(rtld_bind_lock, &lockstate); 3002217223Skib } 3003199829Skib lo_flags = RTLD_LO_DLOPEN; 3004216695Skib if (mode & RTLD_NODELETE) 3005216695Skib lo_flags |= RTLD_LO_NODELETE; 3006199829Skib if (mode & RTLD_NOLOAD) 3007199829Skib lo_flags |= RTLD_LO_NOLOAD; 3008199877Skib if (ld_tracing != NULL) 3009199877Skib lo_flags |= RTLD_LO_TRACE; 301090172Ssobomax 3011229768Skib return (dlopen_object(name, fd, obj_main, lo_flags, 3012234170Skib mode & (RTLD_MODEMASK | RTLD_GLOBAL), NULL)); 3013216695Skib} 3014216695Skib 3015228503Skibstatic void 3016228503Skibdlopen_cleanup(Obj_Entry *obj) 3017228503Skib{ 3018228503Skib 3019228503Skib obj->dl_refcount--; 3020228503Skib unref_dag(obj); 3021228503Skib if (obj->refcount == 0) 3022228503Skib unload_object(obj); 3023228503Skib} 3024228503Skib 3025216695Skibstatic Obj_Entry * 3026229768Skibdlopen_object(const char *name, int fd, Obj_Entry *refobj, int lo_flags, 3027234170Skib int mode, RtldLockState *lockstate) 3028216695Skib{ 3029296727Skib Obj_Entry *old_obj_tail; 3030216695Skib Obj_Entry *obj; 3031216695Skib Objlist initlist; 3032234170Skib RtldLockState mlockstate; 3033216695Skib int result; 3034216695Skib 303563870Sjdp objlist_init(&initlist); 303655687Sjdp 3037234170Skib if (lockstate == NULL && !(lo_flags & RTLD_LO_EARLY)) { 3038234170Skib wlock_acquire(rtld_bind_lock, &mlockstate); 3039234170Skib lockstate = &mlockstate; 3040234170Skib } 304165109Sjwd GDB_STATE(RT_ADD,NULL); 304235529Sdfr 3043296727Skib old_obj_tail = globallist_curr(TAILQ_LAST(&obj_list, obj_entry_q)); 304455122Sjdp obj = NULL; 3045229768Skib if (name == NULL && fd == -1) { 304634192Sjdp obj = obj_main; 304748208Sjdp obj->refcount++; 304848208Sjdp } else { 3049229768Skib obj = load_object(name, fd, refobj, lo_flags); 305034192Sjdp } 305134192Sjdp 305235529Sdfr if (obj) { 305335529Sdfr obj->dl_refcount++; 305450608Sjdp if (mode & RTLD_GLOBAL && objlist_find(&list_global, obj) == NULL) 305563870Sjdp objlist_push_tail(&list_global, obj); 3056296727Skib if (globallist_next(old_obj_tail) != NULL) { 3057296727Skib /* We loaded something new. */ 3058296727Skib assert(globallist_next(old_obj_tail) == obj); 3059233231Skib result = load_needed_objects(obj, 3060233231Skib lo_flags & (RTLD_LO_DLOPEN | RTLD_LO_EARLY)); 3061153648Skan init_dag(obj); 3062214777Skib ref_dag(obj); 3063153515Skan if (result != -1) 3064153515Skan result = rtld_verify_versions(&obj->dagmembers); 3065105439Ssobomax if (result != -1 && ld_tracing) 3066105439Ssobomax goto trace; 3067237659Skib if (result == -1 || relocate_object_dag(obj, 3068237659Skib (mode & RTLD_MODEMASK) == RTLD_NOW, &obj_rtld, 3069233231Skib (lo_flags & RTLD_LO_EARLY) ? SYMLOOK_EARLY : 0, 3070237659Skib lockstate) == -1) { 3071228503Skib dlopen_cleanup(obj); 307235529Sdfr obj = NULL; 3073233231Skib } else if (lo_flags & RTLD_LO_EARLY) { 3074233231Skib /* 3075233231Skib * Do not call the init functions for early loaded 3076233231Skib * filtees. The image is still not initialized enough 3077233231Skib * for them to work. 3078233231Skib * 3079233231Skib * Our object is found by the global object list and 3080233231Skib * will be ordered among all init calls done right 3081233231Skib * before transferring control to main. 3082233231Skib */ 308355687Sjdp } else { 308463870Sjdp /* Make list of init functions to call. */ 3085296727Skib initlist_add_objects(obj, obj, &initlist); 308655687Sjdp } 3087239253Skan /* 3088281849Skib * Process all no_delete or global objects here, given 3089281849Skib * them own DAGs to prevent their dependencies from being 3090281849Skib * unloaded. This has to be done after we have loaded all 3091281849Skib * of the dependencies, so that we do not miss any. 3092239253Skan */ 3093239470Skan if (obj != NULL) 3094281849Skib process_z(obj); 3095114826Skan } else { 3096214728Skib /* 3097214728Skib * Bump the reference counts for objects on this DAG. If 3098214728Skib * this is the first dlopen() call for the object that was 3099214728Skib * already loaded as a dependency, initialize the dag 3100214728Skib * starting at it. 3101214728Skib */ 3102214777Skib init_dag(obj); 3103214777Skib ref_dag(obj); 3104114826Skan 3105216695Skib if ((lo_flags & RTLD_LO_TRACE) != 0) 3106114826Skan goto trace; 3107114826Skan } 3108216695Skib if (obj != NULL && ((lo_flags & RTLD_LO_NODELETE) != 0 || 3109216695Skib obj->z_nodelete) && !obj->ref_nodel) { 3110190543Skib dbg("obj %s nodelete", obj->path); 3111190543Skib ref_dag(obj); 3112190543Skib obj->z_nodelete = obj->ref_nodel = true; 3113190543Skib } 311434192Sjdp } 311535529Sdfr 3116165916Sjhb LD_UTRACE(UTRACE_DLOPEN_STOP, obj, NULL, 0, obj ? obj->dl_refcount : 0, 3117165916Sjhb name); 311865109Sjwd GDB_STATE(RT_CONSISTENT,obj ? &obj->linkmap : NULL); 311955687Sjdp 3120233777Skan if (!(lo_flags & RTLD_LO_EARLY)) { 3121234170Skib map_stacks_exec(lockstate); 3122233777Skan } 3123233777Skan 3124228503Skib if (initlist_objects_ifunc(&initlist, (mode & RTLD_MODEMASK) == RTLD_NOW, 3125233231Skib (lo_flags & RTLD_LO_EARLY) ? SYMLOOK_EARLY : 0, 3126234170Skib lockstate) == -1) { 3127228503Skib objlist_clear(&initlist); 3128228503Skib dlopen_cleanup(obj); 3129234170Skib if (lockstate == &mlockstate) 3130234170Skib lock_release(rtld_bind_lock, lockstate); 3131228503Skib return (NULL); 3132228503Skib } 3133228503Skib 3134233231Skib if (!(lo_flags & RTLD_LO_EARLY)) { 3135233231Skib /* Call the init functions. */ 3136234170Skib objlist_call_init(&initlist, lockstate); 3137233231Skib } 313863870Sjdp objlist_clear(&initlist); 3139234170Skib if (lockstate == &mlockstate) 3140234170Skib lock_release(rtld_bind_lock, lockstate); 314134192Sjdp return obj; 3142105439Ssobomaxtrace: 3143105439Ssobomax trace_loaded_objects(obj); 3144234170Skib if (lockstate == &mlockstate) 3145234170Skib lock_release(rtld_bind_lock, lockstate); 3146105439Ssobomax exit(0); 314734192Sjdp} 314834192Sjdp 3149153515Skanstatic void * 3150153515Skando_dlsym(void *handle, const char *name, void *retaddr, const Ver_Entry *ve, 3151153515Skan int flags) 315234192Sjdp{ 3153162449Sjkim DoneList donelist; 3154162449Sjkim const Obj_Entry *obj, *defobj; 3155216695Skib const Elf_Sym *def; 3156216695Skib SymLook req; 3157216695Skib RtldLockState lockstate; 3158233674Skib#ifndef __ia64__ 3159233655Skib tls_index ti; 3160233674Skib#endif 3161284954Sdes void *sym; 3162216695Skib int res; 316334192Sjdp 316438737Sjdp def = NULL; 316550608Sjdp defobj = NULL; 3166216695Skib symlook_init(&req, name); 3167216695Skib req.ventry = ve; 3168216695Skib req.flags = flags | SYMLOOK_IN_PLT; 3169216695Skib req.lockstate = &lockstate; 317034192Sjdp 3171284954Sdes LD_UTRACE(UTRACE_DLSYM_START, handle, NULL, 0, 0, name); 3172216695Skib rlock_acquire(rtld_bind_lock, &lockstate); 3173218476Skib if (sigsetjmp(lockstate.env, 0) != 0) 3174216695Skib lock_upgrade(rtld_bind_lock, &lockstate); 3175110804Skan if (handle == NULL || handle == RTLD_NEXT || 3176110804Skan handle == RTLD_DEFAULT || handle == RTLD_SELF) { 317734192Sjdp 317834192Sjdp if ((obj = obj_from_addr(retaddr)) == NULL) { 317934192Sjdp _rtld_error("Cannot determine caller's shared object"); 3180216695Skib lock_release(rtld_bind_lock, &lockstate); 3181284954Sdes LD_UTRACE(UTRACE_DLSYM_STOP, handle, NULL, 0, 0, name); 318234192Sjdp return NULL; 318334192Sjdp } 318450608Sjdp if (handle == NULL) { /* Just the caller's shared object. */ 3185216695Skib res = symlook_obj(&req, obj); 3186216695Skib if (res == 0) { 3187216695Skib def = req.sym_out; 3188216695Skib defobj = req.defobj_out; 3189216695Skib } 3190110804Skan } else if (handle == RTLD_NEXT || /* Objects after caller's */ 3191110804Skan handle == RTLD_SELF) { /* ... caller included */ 3192110804Skan if (handle == RTLD_NEXT) 3193296727Skib obj = globallist_next(obj); 3194303169Sbdrewery for (; obj != NULL; obj = TAILQ_NEXT(obj, next)) { 3195296727Skib if (obj->marker) 3196296727Skib continue; 3197216695Skib res = symlook_obj(&req, obj); 3198216695Skib if (res == 0) { 3199216695Skib if (def == NULL || 3200216695Skib ELF_ST_BIND(req.sym_out->st_info) != STB_WEAK) { 3201216695Skib def = req.sym_out; 3202216695Skib defobj = req.defobj_out; 3203183737Skan if (ELF_ST_BIND(def->st_info) != STB_WEAK) 3204183737Skan break; 3205183737Skan } 320650608Sjdp } 320750608Sjdp } 3208183737Skan /* 3209183737Skan * Search the dynamic linker itself, and possibly resolve the 3210183737Skan * symbol from there. This is how the application links to 3211211749Skib * dynamic linker services such as dlopen. 3212183737Skan */ 3213183737Skan if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { 3214216695Skib res = symlook_obj(&req, &obj_rtld); 3215216695Skib if (res == 0) { 3216216695Skib def = req.sym_out; 3217216695Skib defobj = req.defobj_out; 3218183737Skan } 3219183737Skan } 322066056Sjdp } else { 322166056Sjdp assert(handle == RTLD_DEFAULT); 3222216728Skan res = symlook_default(&req, obj); 3223216695Skib if (res == 0) { 3224216695Skib defobj = req.defobj_out; 3225216695Skib def = req.sym_out; 3226216695Skib } 322738737Sjdp } 322834192Sjdp } else { 322955122Sjdp if ((obj = dlcheck(handle)) == NULL) { 3230216695Skib lock_release(rtld_bind_lock, &lockstate); 3231284954Sdes LD_UTRACE(UTRACE_DLSYM_STOP, handle, NULL, 0, 0, name); 323234192Sjdp return NULL; 323355122Sjdp } 323438737Sjdp 3235162156Skib donelist_init(&donelist); 323638737Sjdp if (obj->mainprog) { 3237218051Skan /* Handle obtained by dlopen(NULL, ...) implies global scope. */ 3238218051Skan res = symlook_global(&req, &donelist); 3239216695Skib if (res == 0) { 3240216695Skib def = req.sym_out; 3241216695Skib defobj = req.defobj_out; 3242218051Skan } 3243218051Skan /* 3244218051Skan * Search the dynamic linker itself, and possibly resolve the 3245218051Skan * symbol from there. This is how the application links to 3246218051Skan * dynamic linker services such as dlopen. 3247218051Skan */ 3248218051Skan if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { 3249218051Skan res = symlook_obj(&req, &obj_rtld); 3250216695Skib if (res == 0) { 3251216695Skib def = req.sym_out; 3252216695Skib defobj = req.defobj_out; 3253216695Skib } 3254216695Skib } 3255218051Skan } 3256218051Skan else { 3257162156Skib /* Search the whole DAG rooted at the given object. */ 3258218051Skan res = symlook_list(&req, &obj->dagmembers, &donelist); 3259216695Skib if (res == 0) { 3260216695Skib def = req.sym_out; 3261216695Skib defobj = req.defobj_out; 3262216695Skib } 326338737Sjdp } 326434192Sjdp } 326534192Sjdp 326655122Sjdp if (def != NULL) { 3267216695Skib lock_release(rtld_bind_lock, &lockstate); 326885004Sdfr 326985004Sdfr /* 327085004Sdfr * The value required by the caller is derived from the value 327185004Sdfr * of the symbol. For the ia64 architecture, we need to 327285004Sdfr * construct a function descriptor which the caller can use to 327385004Sdfr * call the function with the right 'gp' value. For other 327485004Sdfr * architectures and for non-functions, the value is simply 327585004Sdfr * the relocated value of the symbol. 327685004Sdfr */ 327785004Sdfr if (ELF_ST_TYPE(def->st_info) == STT_FUNC) 3278284954Sdes sym = make_function_pointer(def, defobj); 3279228435Skib else if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) 3280284954Sdes sym = rtld_resolve_ifunc(defobj, def); 3281233655Skib else if (ELF_ST_TYPE(def->st_info) == STT_TLS) { 3282233674Skib#ifdef __ia64__ 3283233674Skib return (__tls_get_addr(defobj->tlsindex, def->st_value)); 3284233674Skib#else 3285233655Skib ti.ti_module = defobj->tlsindex; 3286233655Skib ti.ti_offset = def->st_value; 3287284954Sdes sym = __tls_get_addr(&ti); 3288233674Skib#endif 3289233655Skib } else 3290284954Sdes sym = defobj->relocbase + def->st_value; 3291284954Sdes LD_UTRACE(UTRACE_DLSYM_STOP, handle, sym, 0, 0, name); 3292284954Sdes return (sym); 329355122Sjdp } 329434192Sjdp 3295320888Skib _rtld_error("Undefined symbol \"%s%s%s\"", name, ve != NULL ? "@" : "", 3296320888Skib ve != NULL ? ve->name : ""); 3297216695Skib lock_release(rtld_bind_lock, &lockstate); 3298284954Sdes LD_UTRACE(UTRACE_DLSYM_STOP, handle, NULL, 0, 0, name); 329934192Sjdp return NULL; 330034192Sjdp} 330134192Sjdp 3302153515Skanvoid * 3303153515Skandlsym(void *handle, const char *name) 3304153515Skan{ 3305153515Skan return do_dlsym(handle, name, __builtin_return_address(0), NULL, 3306153515Skan SYMLOOK_DLSYM); 3307153515Skan} 3308153515Skan 3309190673Skibdlfunc_t 3310190673Skibdlfunc(void *handle, const char *name) 3311190673Skib{ 3312190673Skib union { 3313190673Skib void *d; 3314190673Skib dlfunc_t f; 3315190673Skib } rv; 3316190673Skib 3317190673Skib rv.d = do_dlsym(handle, name, __builtin_return_address(0), NULL, 3318190673Skib SYMLOOK_DLSYM); 3319190673Skib return (rv.f); 3320190673Skib} 3321190673Skib 3322153515Skanvoid * 3323153515Skandlvsym(void *handle, const char *name, const char *version) 3324153515Skan{ 3325153515Skan Ver_Entry ventry; 3326153515Skan 3327153515Skan ventry.name = version; 3328153515Skan ventry.file = NULL; 3329153515Skan ventry.hash = elf_hash(version); 3330153515Skan ventry.flags= 0; 3331153515Skan return do_dlsym(handle, name, __builtin_return_address(0), &ventry, 3332153515Skan SYMLOOK_DLSYM); 3333153515Skan} 3334153515Skan 333545015Snateint 3336211705Skib_rtld_addr_phdr(const void *addr, struct dl_phdr_info *phdr_info) 3337211705Skib{ 3338211705Skib const Obj_Entry *obj; 3339216695Skib RtldLockState lockstate; 3340211705Skib 3341216695Skib rlock_acquire(rtld_bind_lock, &lockstate); 3342211705Skib obj = obj_from_addr(addr); 3343211705Skib if (obj == NULL) { 3344211705Skib _rtld_error("No shared object contains address"); 3345216695Skib lock_release(rtld_bind_lock, &lockstate); 3346211705Skib return (0); 3347211705Skib } 3348211705Skib rtld_fill_dl_phdr_info(obj, phdr_info); 3349216695Skib lock_release(rtld_bind_lock, &lockstate); 3350211705Skib return (1); 3351211705Skib} 3352211705Skib 3353211705Skibint 335445015Snatedladdr(const void *addr, Dl_info *info) 335545015Snate{ 335645015Snate const Obj_Entry *obj; 335745015Snate const Elf_Sym *def; 335845015Snate void *symbol_addr; 335945015Snate unsigned long symoffset; 3360216695Skib RtldLockState lockstate; 3361115396Skan 3362216695Skib rlock_acquire(rtld_bind_lock, &lockstate); 336345018Snate obj = obj_from_addr(addr); 336445015Snate if (obj == NULL) { 336545018Snate _rtld_error("No shared object contains address"); 3366216695Skib lock_release(rtld_bind_lock, &lockstate); 336745015Snate return 0; 336845015Snate } 336945015Snate info->dli_fname = obj->path; 337045018Snate info->dli_fbase = obj->mapbase; 337145015Snate info->dli_saddr = (void *)0; 337245015Snate info->dli_sname = NULL; 337345015Snate 337445015Snate /* 337545399Sjdp * Walk the symbol list looking for the symbol whose address is 337645015Snate * closest to the address sent in. 337745015Snate */ 3378234841Skib for (symoffset = 0; symoffset < obj->dynsymcount; symoffset++) { 337945015Snate def = obj->symtab + symoffset; 338045018Snate 338145015Snate /* 338245018Snate * For skip the symbol if st_shndx is either SHN_UNDEF or 338345018Snate * SHN_COMMON. 338445018Snate */ 338545018Snate if (def->st_shndx == SHN_UNDEF || def->st_shndx == SHN_COMMON) 338645018Snate continue; 338745018Snate 338845018Snate /* 338945399Sjdp * If the symbol is greater than the specified address, or if it 339045015Snate * is further away from addr than the current nearest symbol, 339145015Snate * then reject it. 339245015Snate */ 339345018Snate symbol_addr = obj->relocbase + def->st_value; 339445018Snate if (symbol_addr > addr || symbol_addr < info->dli_saddr) 339545015Snate continue; 339645015Snate 339745015Snate /* Update our idea of the nearest symbol. */ 339845015Snate info->dli_sname = obj->strtab + def->st_name; 339945015Snate info->dli_saddr = symbol_addr; 340045015Snate 340145015Snate /* Exact match? */ 340245015Snate if (info->dli_saddr == addr) 340345015Snate break; 340445015Snate } 3405216695Skib lock_release(rtld_bind_lock, &lockstate); 340645015Snate return 1; 340745015Snate} 340845015Snate 3409110804Skanint 3410110804Skandlinfo(void *handle, int request, void *p) 3411110804Skan{ 3412110804Skan const Obj_Entry *obj; 3413216695Skib RtldLockState lockstate; 3414216695Skib int error; 3415110804Skan 3416216695Skib rlock_acquire(rtld_bind_lock, &lockstate); 3417110804Skan 3418110804Skan if (handle == NULL || handle == RTLD_SELF) { 3419110804Skan void *retaddr; 3420110804Skan 3421110804Skan retaddr = __builtin_return_address(0); /* __GNUC__ only */ 3422110804Skan if ((obj = obj_from_addr(retaddr)) == NULL) 3423110804Skan _rtld_error("Cannot determine caller's shared object"); 3424110804Skan } else 3425110804Skan obj = dlcheck(handle); 3426110804Skan 3427110804Skan if (obj == NULL) { 3428216695Skib lock_release(rtld_bind_lock, &lockstate); 3429110804Skan return (-1); 3430110804Skan } 3431110804Skan 3432110804Skan error = 0; 3433110804Skan switch (request) { 3434110804Skan case RTLD_DI_LINKMAP: 3435110804Skan *((struct link_map const **)p) = &obj->linkmap; 3436110804Skan break; 3437110804Skan case RTLD_DI_ORIGIN: 3438110804Skan error = rtld_dirname(obj->path, p); 3439110804Skan break; 3440110804Skan 3441110804Skan case RTLD_DI_SERINFOSIZE: 3442110804Skan case RTLD_DI_SERINFO: 3443110804Skan error = do_search_info(obj, request, (struct dl_serinfo *)p); 3444110804Skan break; 3445110804Skan 3446110804Skan default: 3447110804Skan _rtld_error("Invalid request %d passed to dlinfo()", request); 3448110804Skan error = -1; 3449110804Skan } 3450110804Skan 3451216695Skib lock_release(rtld_bind_lock, &lockstate); 3452110804Skan 3453110804Skan return (error); 3454110804Skan} 3455110804Skan 3456211705Skibstatic void 3457211705Skibrtld_fill_dl_phdr_info(const Obj_Entry *obj, struct dl_phdr_info *phdr_info) 3458211705Skib{ 3459211705Skib 3460211705Skib phdr_info->dlpi_addr = (Elf_Addr)obj->relocbase; 3461274531Semaste phdr_info->dlpi_name = obj->path; 3462211705Skib phdr_info->dlpi_phdr = obj->phdr; 3463211705Skib phdr_info->dlpi_phnum = obj->phsize / sizeof(obj->phdr[0]); 3464211705Skib phdr_info->dlpi_tls_modid = obj->tlsindex; 3465211705Skib phdr_info->dlpi_tls_data = obj->tlsinit; 3466211705Skib phdr_info->dlpi_adds = obj_loads; 3467211705Skib phdr_info->dlpi_subs = obj_loads - obj_count; 3468211705Skib} 3469211705Skib 3470168312Skanint 3471168312Skandl_iterate_phdr(__dl_iterate_hdr_callback callback, void *param) 3472168312Skan{ 3473296727Skib struct dl_phdr_info phdr_info; 3474296727Skib Obj_Entry *obj, marker; 3475296727Skib RtldLockState bind_lockstate, phdr_lockstate; 3476296727Skib int error; 3477168312Skan 3478296727Skib bzero(&marker, sizeof(marker)); 3479296727Skib marker.marker = true; 3480296727Skib error = 0; 3481168312Skan 3482296727Skib wlock_acquire(rtld_phdr_lock, &phdr_lockstate); 3483312700Sbdrewery wlock_acquire(rtld_bind_lock, &bind_lockstate); 3484296727Skib for (obj = globallist_curr(TAILQ_FIRST(&obj_list)); obj != NULL;) { 3485296727Skib TAILQ_INSERT_AFTER(&obj_list, obj, &marker, next); 3486296727Skib rtld_fill_dl_phdr_info(obj, &phdr_info); 3487296727Skib lock_release(rtld_bind_lock, &bind_lockstate); 3488168312Skan 3489296727Skib error = callback(&phdr_info, sizeof phdr_info, param); 3490168312Skan 3491312700Sbdrewery wlock_acquire(rtld_bind_lock, &bind_lockstate); 3492296727Skib obj = globallist_next(&marker); 3493296727Skib TAILQ_REMOVE(&obj_list, &marker, next); 3494296727Skib if (error != 0) { 3495296727Skib lock_release(rtld_bind_lock, &bind_lockstate); 3496296727Skib lock_release(rtld_phdr_lock, &phdr_lockstate); 3497296727Skib return (error); 3498296727Skib } 3499296727Skib } 3500168312Skan 3501296727Skib if (error == 0) { 3502296727Skib rtld_fill_dl_phdr_info(&obj_rtld, &phdr_info); 3503296727Skib lock_release(rtld_bind_lock, &bind_lockstate); 3504296727Skib error = callback(&phdr_info, sizeof(phdr_info), param); 3505296727Skib } 3506296727Skib lock_release(rtld_phdr_lock, &phdr_lockstate); 3507296727Skib return (error); 3508168312Skan} 3509168312Skan 3510110804Skanstatic void * 3511110804Skanfill_search_info(const char *dir, size_t dirlen, void *param) 3512110804Skan{ 3513110804Skan struct fill_search_info_args *arg; 3514110804Skan 3515110804Skan arg = param; 3516110804Skan 3517110804Skan if (arg->request == RTLD_DI_SERINFOSIZE) { 3518110804Skan arg->serinfo->dls_cnt ++; 3519238471Skib arg->serinfo->dls_size += sizeof(struct dl_serpath) + dirlen + 1; 3520110804Skan } else { 3521110804Skan struct dl_serpath *s_entry; 3522110804Skan 3523110804Skan s_entry = arg->serpath; 3524110804Skan s_entry->dls_name = arg->strspace; 3525110804Skan s_entry->dls_flags = arg->flags; 3526110804Skan 3527110804Skan strncpy(arg->strspace, dir, dirlen); 3528110804Skan arg->strspace[dirlen] = '\0'; 3529110804Skan 3530110804Skan arg->strspace += dirlen + 1; 3531110804Skan arg->serpath++; 3532110804Skan } 3533110804Skan 3534110804Skan return (NULL); 3535110804Skan} 3536110804Skan 3537110804Skanstatic int 3538110804Skando_search_info(const Obj_Entry *obj, int request, struct dl_serinfo *info) 3539110804Skan{ 3540110804Skan struct dl_serinfo _info; 3541110804Skan struct fill_search_info_args args; 3542110804Skan 3543110804Skan args.request = RTLD_DI_SERINFOSIZE; 3544110804Skan args.serinfo = &_info; 3545110804Skan 3546110804Skan _info.dls_size = __offsetof(struct dl_serinfo, dls_serpath); 3547110804Skan _info.dls_cnt = 0; 3548110804Skan 3549238471Skib path_enumerate(obj->rpath, fill_search_info, &args); 3550110804Skan path_enumerate(ld_library_path, fill_search_info, &args); 3551238471Skib path_enumerate(obj->runpath, fill_search_info, &args); 3552238471Skib path_enumerate(gethints(obj->z_nodeflib), fill_search_info, &args); 3553238471Skib if (!obj->z_nodeflib) 3554238471Skib path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &args); 3555110804Skan 3556110804Skan 3557110804Skan if (request == RTLD_DI_SERINFOSIZE) { 3558110804Skan info->dls_size = _info.dls_size; 3559110804Skan info->dls_cnt = _info.dls_cnt; 3560110804Skan return (0); 3561110804Skan } 3562110804Skan 3563110804Skan if (info->dls_cnt != _info.dls_cnt || info->dls_size != _info.dls_size) { 3564110804Skan _rtld_error("Uninitialized Dl_serinfo struct passed to dlinfo()"); 3565110804Skan return (-1); 3566110804Skan } 3567110804Skan 3568110804Skan args.request = RTLD_DI_SERINFO; 3569110804Skan args.serinfo = info; 3570110804Skan args.serpath = &info->dls_serpath[0]; 3571110804Skan args.strspace = (char *)&info->dls_serpath[_info.dls_cnt]; 3572110804Skan 3573238471Skib args.flags = LA_SER_RUNPATH; 3574238471Skib if (path_enumerate(obj->rpath, fill_search_info, &args) != NULL) 3575238471Skib return (-1); 3576238471Skib 3577110804Skan args.flags = LA_SER_LIBPATH; 3578110804Skan if (path_enumerate(ld_library_path, fill_search_info, &args) != NULL) 3579110804Skan return (-1); 3580110804Skan 3581110804Skan args.flags = LA_SER_RUNPATH; 3582238471Skib if (path_enumerate(obj->runpath, fill_search_info, &args) != NULL) 3583110804Skan return (-1); 3584110804Skan 3585110804Skan args.flags = LA_SER_CONFIG; 3586238471Skib if (path_enumerate(gethints(obj->z_nodeflib), fill_search_info, &args) 3587238471Skib != NULL) 3588110804Skan return (-1); 3589110804Skan 3590110804Skan args.flags = LA_SER_DEFAULT; 3591238471Skib if (!obj->z_nodeflib && 3592238471Skib path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &args) != NULL) 3593110804Skan return (-1); 3594110804Skan return (0); 3595110804Skan} 3596110804Skan 3597110804Skanstatic int 3598110804Skanrtld_dirname(const char *path, char *bname) 3599110804Skan{ 3600110804Skan const char *endp; 3601110804Skan 3602110804Skan /* Empty or NULL string gets treated as "." */ 3603110804Skan if (path == NULL || *path == '\0') { 3604110804Skan bname[0] = '.'; 3605110834Skan bname[1] = '\0'; 3606110804Skan return (0); 3607110804Skan } 3608110804Skan 3609110804Skan /* Strip trailing slashes */ 3610110804Skan endp = path + strlen(path) - 1; 3611110804Skan while (endp > path && *endp == '/') 3612110804Skan endp--; 3613110804Skan 3614110804Skan /* Find the start of the dir */ 3615110804Skan while (endp > path && *endp != '/') 3616110804Skan endp--; 3617110804Skan 3618110804Skan /* Either the dir is "/" or there are no slashes */ 3619110804Skan if (endp == path) { 3620110804Skan bname[0] = *endp == '/' ? '/' : '.'; 3621110804Skan bname[1] = '\0'; 3622110804Skan return (0); 3623110804Skan } else { 3624110804Skan do { 3625110804Skan endp--; 3626110804Skan } while (endp > path && *endp == '/'); 3627110804Skan } 3628110804Skan 3629110804Skan if (endp - path + 2 > PATH_MAX) 3630110804Skan { 3631110804Skan _rtld_error("Filename is too long: %s", path); 3632110804Skan return(-1); 3633110804Skan } 3634110804Skan 3635110804Skan strncpy(bname, path, endp - path + 1); 3636110804Skan bname[endp - path + 1] = '\0'; 3637110804Skan return (0); 3638110804Skan} 3639110804Skan 3640189959Skibstatic int 3641189959Skibrtld_dirname_abs(const char *path, char *base) 3642189959Skib{ 3643279713Sjkim char *last; 3644189959Skib 3645279713Sjkim if (realpath(path, base) == NULL) 3646189959Skib return (-1); 3647279713Sjkim dbg("%s -> %s", path, base); 3648279713Sjkim last = strrchr(base, '/'); 3649279713Sjkim if (last == NULL) 3650189959Skib return (-1); 3651279713Sjkim if (last != base) 3652279713Sjkim *last = '\0'; 3653189959Skib return (0); 3654189959Skib} 3655189959Skib 365634192Sjdpstatic void 365735529Sdfrlinkmap_add(Obj_Entry *obj) 365835529Sdfr{ 365935529Sdfr struct link_map *l = &obj->linkmap; 366035529Sdfr struct link_map *prev; 366135529Sdfr 366235529Sdfr obj->linkmap.l_name = obj->path; 366335529Sdfr obj->linkmap.l_addr = obj->mapbase; 366435529Sdfr obj->linkmap.l_ld = obj->dynamic; 366535529Sdfr#ifdef __mips__ 366635529Sdfr /* GDB needs load offset on MIPS to use the symbols */ 366735529Sdfr obj->linkmap.l_offs = obj->relocbase; 366835529Sdfr#endif 366935529Sdfr 367035529Sdfr if (r_debug.r_map == NULL) { 367135529Sdfr r_debug.r_map = l; 367235529Sdfr return; 367335529Sdfr } 3674110804Skan 367539321Sjdp /* 367639321Sjdp * Scan to the end of the list, but not past the entry for the 367739321Sjdp * dynamic linker, which we want to keep at the very end. 367839321Sjdp */ 367939321Sjdp for (prev = r_debug.r_map; 368039321Sjdp prev->l_next != NULL && prev->l_next != &obj_rtld.linkmap; 368139321Sjdp prev = prev->l_next) 368235529Sdfr ; 368339321Sjdp 368439321Sjdp /* Link in the new entry. */ 368535529Sdfr l->l_prev = prev; 368639321Sjdp l->l_next = prev->l_next; 368739321Sjdp if (l->l_next != NULL) 368839321Sjdp l->l_next->l_prev = l; 368935529Sdfr prev->l_next = l; 369035529Sdfr} 369135529Sdfr 369238739Sjdpstatic void 369338739Sjdplinkmap_delete(Obj_Entry *obj) 369435529Sdfr{ 369535529Sdfr struct link_map *l = &obj->linkmap; 369635529Sdfr 369735529Sdfr if (l->l_prev == NULL) { 369835529Sdfr if ((r_debug.r_map = l->l_next) != NULL) 369935529Sdfr l->l_next->l_prev = NULL; 370035529Sdfr return; 370135529Sdfr } 370235529Sdfr 370335529Sdfr if ((l->l_prev->l_next = l->l_next) != NULL) 370435529Sdfr l->l_next->l_prev = l->l_prev; 370535529Sdfr} 370635574Sdfr 370738739Sjdp/* 370838739Sjdp * Function for the debugger to set a breakpoint on to gain control. 370965109Sjwd * 371065109Sjwd * The two parameters allow the debugger to easily find and determine 371165109Sjwd * what the runtime loader is doing and to whom it is doing it. 371265109Sjwd * 371365109Sjwd * When the loadhook trap is hit (r_debug_state, set at program 371465109Sjwd * initialization), the arguments can be found on the stack: 371565109Sjwd * 371665109Sjwd * +8 struct link_map *m 371765109Sjwd * +4 struct r_debug *rd 371865109Sjwd * +0 RetAddr 371938739Sjdp */ 372038739Sjdpvoid 372165109Sjwdr_debug_state(struct r_debug* rd, struct link_map *m) 372235574Sdfr{ 3723225366Sdim /* 3724225366Sdim * The following is a hack to force the compiler to emit calls to 3725225366Sdim * this function, even when optimizing. If the function is empty, 3726225366Sdim * the compiler is not obliged to emit any code for calls to it, 3727225366Sdim * even when marked __noinline. However, gdb depends on those 3728225366Sdim * calls being made. 3729225366Sdim */ 3730269680Smarkj __compiler_membar(); 373138739Sjdp} 373238739Sjdp 373338739Sjdp/* 3734269680Smarkj * A function called after init routines have completed. This can be used to 3735269680Smarkj * break before a program's entry routine is called, and can be used when 3736269680Smarkj * main is not available in the symbol table. 3737269680Smarkj */ 3738269680Smarkjvoid 3739269680Smarkj_r_debug_postinit(struct link_map *m) 3740269680Smarkj{ 3741269680Smarkj 3742269680Smarkj /* See r_debug_state(). */ 3743269680Smarkj __compiler_membar(); 3744269680Smarkj} 3745269680Smarkj 3746269680Smarkj/* 374790172Ssobomax * Get address of the pointer variable in the main program. 3748217223Skib * Prefer non-weak symbol over the weak one. 374945890Sjdp */ 375090172Ssobomaxstatic const void ** 3751217223Skibget_program_var_addr(const char *name, RtldLockState *lockstate) 375245890Sjdp{ 3753216695Skib SymLook req; 3754217223Skib DoneList donelist; 375545890Sjdp 3756216695Skib symlook_init(&req, name); 3757217223Skib req.lockstate = lockstate; 3758217223Skib donelist_init(&donelist); 3759217223Skib if (symlook_global(&req, &donelist) != 0) 3760217223Skib return (NULL); 3761217849Skib if (ELF_ST_TYPE(req.sym_out->st_info) == STT_FUNC) 3762217849Skib return ((const void **)make_function_pointer(req.sym_out, 3763217849Skib req.defobj_out)); 3764228435Skib else if (ELF_ST_TYPE(req.sym_out->st_info) == STT_GNU_IFUNC) 3765228435Skib return ((const void **)rtld_resolve_ifunc(req.defobj_out, req.sym_out)); 3766217849Skib else 3767217849Skib return ((const void **)(req.defobj_out->relocbase + 3768217849Skib req.sym_out->st_value)); 376945890Sjdp} 377045890Sjdp 377166056Sjdp/* 377290172Ssobomax * Set a pointer variable in the main program to the given value. This 377390172Ssobomax * is used to set key variables such as "environ" before any of the 377490172Ssobomax * init functions are called. 377590172Ssobomax */ 377690172Ssobomaxstatic void 377790172Ssobomaxset_program_var(const char *name, const void *value) 377890172Ssobomax{ 377990172Ssobomax const void **addr; 378090172Ssobomax 3781217223Skib if ((addr = get_program_var_addr(name, NULL)) != NULL) { 378290172Ssobomax dbg("\"%s\": *%p <-- %p", name, addr, value); 378390172Ssobomax *addr = value; 378490172Ssobomax } 378590172Ssobomax} 378690172Ssobomax 378790172Ssobomax/* 3788217223Skib * Search the global objects, including dependencies and main object, 3789217223Skib * for the given symbol. 3790217223Skib */ 3791217223Skibstatic int 3792217223Skibsymlook_global(SymLook *req, DoneList *donelist) 3793217223Skib{ 3794217223Skib SymLook req1; 3795217223Skib const Objlist_Entry *elm; 3796217223Skib int res; 3797217223Skib 3798217223Skib symlook_init_from_req(&req1, req); 3799217223Skib 3800217223Skib /* Search all objects loaded at program start up. */ 3801217223Skib if (req->defobj_out == NULL || 3802217223Skib ELF_ST_BIND(req->sym_out->st_info) == STB_WEAK) { 3803217223Skib res = symlook_list(&req1, &list_main, donelist); 3804217223Skib if (res == 0 && (req->defobj_out == NULL || 3805217223Skib ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK)) { 3806217223Skib req->sym_out = req1.sym_out; 3807217223Skib req->defobj_out = req1.defobj_out; 3808217223Skib assert(req->defobj_out != NULL); 3809217223Skib } 3810217223Skib } 3811217223Skib 3812217223Skib /* Search all DAGs whose roots are RTLD_GLOBAL objects. */ 3813217223Skib STAILQ_FOREACH(elm, &list_global, link) { 3814217223Skib if (req->defobj_out != NULL && 3815217223Skib ELF_ST_BIND(req->sym_out->st_info) != STB_WEAK) 3816217223Skib break; 3817217223Skib res = symlook_list(&req1, &elm->obj->dagmembers, donelist); 3818217223Skib if (res == 0 && (req->defobj_out == NULL || 3819217223Skib ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK)) { 3820217223Skib req->sym_out = req1.sym_out; 3821217223Skib req->defobj_out = req1.defobj_out; 3822217223Skib assert(req->defobj_out != NULL); 3823217223Skib } 3824217223Skib } 3825217223Skib 3826217223Skib return (req->sym_out != NULL ? 0 : ESRCH); 3827217223Skib} 3828217223Skib 3829217223Skib/* 383066056Sjdp * Given a symbol name in a referencing object, find the corresponding 383166056Sjdp * definition of the symbol. Returns a pointer to the symbol, or NULL if 383266056Sjdp * no definition was found. Returns a pointer to the Obj_Entry of the 383366056Sjdp * defining object via the reference parameter DEFOBJ_OUT. 383466056Sjdp */ 3835216695Skibstatic int 3836216695Skibsymlook_default(SymLook *req, const Obj_Entry *refobj) 383766056Sjdp{ 383866056Sjdp DoneList donelist; 383966056Sjdp const Objlist_Entry *elm; 3840216695Skib SymLook req1; 3841216695Skib int res; 3842217223Skib 384366056Sjdp donelist_init(&donelist); 3844216695Skib symlook_init_from_req(&req1, req); 384566056Sjdp 3846314199Skib /* 3847314199Skib * Look first in the referencing object if linked symbolically, 3848314199Skib * and similarly handle protected symbols. 3849314199Skib */ 3850314199Skib res = symlook_obj(&req1, refobj); 3851314199Skib if (res == 0 && (refobj->symbolic || 3852314199Skib ELF_ST_VISIBILITY(req1.sym_out->st_other) == STV_PROTECTED)) { 3853314199Skib req->sym_out = req1.sym_out; 3854314199Skib req->defobj_out = req1.defobj_out; 3855314199Skib assert(req->defobj_out != NULL); 385666056Sjdp } 3857314199Skib if (refobj->symbolic || req->defobj_out != NULL) 3858314199Skib donelist_check(&donelist, refobj); 385966056Sjdp 3860217223Skib symlook_global(req, &donelist); 386166056Sjdp 3862105492Skan /* Search all dlopened DAGs containing the referencing object. */ 3863105492Skan STAILQ_FOREACH(elm, &refobj->dldags, link) { 3864217223Skib if (req->sym_out != NULL && 3865217223Skib ELF_ST_BIND(req->sym_out->st_info) != STB_WEAK) 3866105492Skan break; 3867216695Skib res = symlook_list(&req1, &elm->obj->dagmembers, &donelist); 3868217223Skib if (res == 0 && (req->sym_out == NULL || 3869217223Skib ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK)) { 3870217223Skib req->sym_out = req1.sym_out; 3871217223Skib req->defobj_out = req1.defobj_out; 3872217223Skib assert(req->defobj_out != NULL); 387366056Sjdp } 387466056Sjdp } 387566056Sjdp 387666056Sjdp /* 387766056Sjdp * Search the dynamic linker itself, and possibly resolve the 387866056Sjdp * symbol from there. This is how the application links to 3879211749Skib * dynamic linker services such as dlopen. 388066056Sjdp */ 3881217223Skib if (req->sym_out == NULL || 3882217223Skib ELF_ST_BIND(req->sym_out->st_info) == STB_WEAK) { 3883216695Skib res = symlook_obj(&req1, &obj_rtld); 3884216695Skib if (res == 0) { 3885217223Skib req->sym_out = req1.sym_out; 3886217223Skib req->defobj_out = req1.defobj_out; 3887217223Skib assert(req->defobj_out != NULL); 388866056Sjdp } 388966056Sjdp } 389066056Sjdp 3891217223Skib return (req->sym_out != NULL ? 0 : ESRCH); 389266056Sjdp} 389366056Sjdp 3894216695Skibstatic int 3895216695Skibsymlook_list(SymLook *req, const Objlist *objlist, DoneList *dlp) 389650608Sjdp{ 389750608Sjdp const Elf_Sym *def; 389850608Sjdp const Obj_Entry *defobj; 389950608Sjdp const Objlist_Entry *elm; 3900216695Skib SymLook req1; 3901216695Skib int res; 390250608Sjdp 390350608Sjdp def = NULL; 390450608Sjdp defobj = NULL; 390550608Sjdp STAILQ_FOREACH(elm, objlist, link) { 390662801Sjdp if (donelist_check(dlp, elm->obj)) 390750608Sjdp continue; 3908216695Skib symlook_init_from_req(&req1, req); 3909216695Skib if ((res = symlook_obj(&req1, elm->obj)) == 0) { 3910216695Skib if (def == NULL || ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK) { 3911216695Skib def = req1.sym_out; 3912216695Skib defobj = req1.defobj_out; 391350608Sjdp if (ELF_ST_BIND(def->st_info) != STB_WEAK) 391450608Sjdp break; 391550608Sjdp } 391650608Sjdp } 391750608Sjdp } 3918216695Skib if (def != NULL) { 3919216695Skib req->sym_out = def; 3920216695Skib req->defobj_out = defobj; 3921216695Skib return (0); 3922216695Skib } 3923216695Skib return (ESRCH); 392450608Sjdp} 392550608Sjdp 392645890Sjdp/* 3927218051Skan * Search the chain of DAGS cointed to by the given Needed_Entry 3928218051Skan * for a symbol of the given name. Each DAG is scanned completely 3929218051Skan * before advancing to the next one. Returns a pointer to the symbol, 3930218051Skan * or NULL if no definition was found. 3931162438Skib */ 3932216695Skibstatic int 3933216695Skibsymlook_needed(SymLook *req, const Needed_Entry *needed, DoneList *dlp) 3934162438Skib{ 3935218051Skan const Elf_Sym *def; 3936162438Skib const Needed_Entry *n; 3937218051Skan const Obj_Entry *defobj; 3938216695Skib SymLook req1; 3939216695Skib int res; 3940162449Sjkim 3941218051Skan def = NULL; 3942162438Skib defobj = NULL; 3943216695Skib symlook_init_from_req(&req1, req); 3944162438Skib for (n = needed; n != NULL; n = n->next) { 3945218051Skan if (n->obj == NULL || 3946218051Skan (res = symlook_list(&req1, &n->obj->dagmembers, dlp)) != 0) 3947162449Sjkim continue; 3948218051Skan if (def == NULL || ELF_ST_BIND(req1.sym_out->st_info) != STB_WEAK) { 3949218051Skan def = req1.sym_out; 3950218051Skan defobj = req1.defobj_out; 3951218051Skan if (ELF_ST_BIND(def->st_info) != STB_WEAK) 3952218051Skan break; 3953162438Skib } 3954162438Skib } 3955216695Skib if (def != NULL) { 3956216695Skib req->sym_out = def; 3957216695Skib req->defobj_out = defobj; 3958216695Skib return (0); 3959216695Skib } 3960216695Skib return (ESRCH); 3961162438Skib} 3962162438Skib 3963162438Skib/* 396438739Sjdp * Search the symbol table of a single shared object for a symbol of 3965153515Skan * the given name and version, if requested. Returns a pointer to the 3966216695Skib * symbol, or NULL if no definition was found. If the object is 3967216695Skib * filter, return filtered symbol from filtee. 396838739Sjdp * 396938739Sjdp * The symbol's hash value is passed in for efficiency reasons; that 397038739Sjdp * eliminates many recomputations of the hash value. 397138739Sjdp */ 3972216695Skibint 3973216695Skibsymlook_obj(SymLook *req, const Obj_Entry *obj) 397438739Sjdp{ 3975216695Skib DoneList donelist; 3976216695Skib SymLook req1; 3977233231Skib int flags, res, mres; 3978216695Skib 3979234841Skib /* 3980235054Skib * If there is at least one valid hash at this point, we prefer to 3981235054Skib * use the faster GNU version if available. 3982234841Skib */ 3983234841Skib if (obj->valid_hash_gnu) 3984234841Skib mres = symlook_obj1_gnu(req, obj); 3985235054Skib else if (obj->valid_hash_sysv) 3986235054Skib mres = symlook_obj1_sysv(req, obj); 3987234841Skib else 3988235054Skib return (EINVAL); 3989234841Skib 3990216695Skib if (mres == 0) { 3991216695Skib if (obj->needed_filtees != NULL) { 3992233231Skib flags = (req->flags & SYMLOOK_EARLY) ? RTLD_LO_EARLY : 0; 3993233231Skib load_filtees(__DECONST(Obj_Entry *, obj), flags, req->lockstate); 3994216695Skib donelist_init(&donelist); 3995216695Skib symlook_init_from_req(&req1, req); 3996216695Skib res = symlook_needed(&req1, obj->needed_filtees, &donelist); 3997216695Skib if (res == 0) { 3998216695Skib req->sym_out = req1.sym_out; 3999216695Skib req->defobj_out = req1.defobj_out; 4000216695Skib } 4001216695Skib return (res); 4002216695Skib } 4003216695Skib if (obj->needed_aux_filtees != NULL) { 4004233231Skib flags = (req->flags & SYMLOOK_EARLY) ? RTLD_LO_EARLY : 0; 4005233231Skib load_filtees(__DECONST(Obj_Entry *, obj), flags, req->lockstate); 4006216695Skib donelist_init(&donelist); 4007216695Skib symlook_init_from_req(&req1, req); 4008216695Skib res = symlook_needed(&req1, obj->needed_aux_filtees, &donelist); 4009216695Skib if (res == 0) { 4010216695Skib req->sym_out = req1.sym_out; 4011216695Skib req->defobj_out = req1.defobj_out; 4012216695Skib return (res); 4013216695Skib } 4014216695Skib } 4015216695Skib } 4016216695Skib return (mres); 4017216695Skib} 4018216695Skib 4019234840Skib/* Symbol match routine common to both hash functions */ 4020234840Skibstatic bool 4021234840Skibmatched_symbol(SymLook *req, const Obj_Entry *obj, Sym_Match_Result *result, 4022234840Skib const unsigned long symnum) 4023216695Skib{ 4024234840Skib Elf_Versym verndx; 4025153515Skan const Elf_Sym *symp; 4026153515Skan const char *strp; 4027153515Skan 4028153515Skan symp = obj->symtab + symnum; 4029153515Skan strp = obj->strtab + symp->st_name; 403038739Sjdp 4031153515Skan switch (ELF_ST_TYPE(symp->st_info)) { 4032153515Skan case STT_FUNC: 4033153515Skan case STT_NOTYPE: 4034153515Skan case STT_OBJECT: 4035234840Skib case STT_COMMON: 4036228435Skib case STT_GNU_IFUNC: 4037234840Skib if (symp->st_value == 0) 4038234840Skib return (false); 4039153515Skan /* fallthrough */ 4040153515Skan case STT_TLS: 4041234840Skib if (symp->st_shndx != SHN_UNDEF) 4042234840Skib break; 4043177924Simp#ifndef __mips__ 4044234840Skib else if (((req->flags & SYMLOOK_IN_PLT) == 0) && 4045234840Skib (ELF_ST_TYPE(symp->st_info) == STT_FUNC)) 4046234840Skib break; 4047153515Skan /* fallthrough */ 4048177924Simp#endif 4049153515Skan default: 4050234840Skib return (false); 405145501Sjdp } 4052216695Skib if (req->name[0] != strp[0] || strcmp(req->name, strp) != 0) 4053234840Skib return (false); 4054153515Skan 4055216695Skib if (req->ventry == NULL) { 4056234840Skib if (obj->versyms != NULL) { 4057234840Skib verndx = VER_NDX(obj->versyms[symnum]); 4058234840Skib if (verndx > obj->vernum) { 4059234840Skib _rtld_error( 4060234840Skib "%s: symbol %s references wrong version %d", 4061234840Skib obj->path, obj->strtab + symnum, verndx); 4062234840Skib return (false); 4063234840Skib } 4064234840Skib /* 4065234840Skib * If we are not called from dlsym (i.e. this 4066234840Skib * is a normal relocation from unversioned 4067234840Skib * binary), accept the symbol immediately if 4068234840Skib * it happens to have first version after this 4069234840Skib * shared object became versioned. Otherwise, 4070234840Skib * if symbol is versioned and not hidden, 4071234840Skib * remember it. If it is the only symbol with 4072234840Skib * this name exported by the shared object, it 4073234840Skib * will be returned as a match by the calling 4074234840Skib * function. If symbol is global (verndx < 2) 4075234840Skib * accept it unconditionally. 4076234840Skib */ 4077234840Skib if ((req->flags & SYMLOOK_DLSYM) == 0 && 4078234840Skib verndx == VER_NDX_GIVEN) { 4079234840Skib result->sym_out = symp; 4080234840Skib return (true); 4081234840Skib } 4082234840Skib else if (verndx >= VER_NDX_GIVEN) { 4083234840Skib if ((obj->versyms[symnum] & VER_NDX_HIDDEN) 4084234840Skib == 0) { 4085234840Skib if (result->vsymp == NULL) 4086234840Skib result->vsymp = symp; 4087234840Skib result->vcount++; 4088234840Skib } 4089234840Skib return (false); 4090234840Skib } 4091153515Skan } 4092234840Skib result->sym_out = symp; 4093234840Skib return (true); 4094234840Skib } 4095234840Skib if (obj->versyms == NULL) { 4096234840Skib if (object_match_name(obj, req->ventry->name)) { 4097234840Skib _rtld_error("%s: object %s should provide version %s " 4098234840Skib "for symbol %s", obj_rtld.path, obj->path, 4099234840Skib req->ventry->name, obj->strtab + symnum); 4100234840Skib return (false); 4101216695Skib } 4102153515Skan } else { 4103153515Skan verndx = VER_NDX(obj->versyms[symnum]); 4104153515Skan if (verndx > obj->vernum) { 4105234840Skib _rtld_error("%s: symbol %s references wrong version %d", 4106234840Skib obj->path, obj->strtab + symnum, verndx); 4107234840Skib return (false); 4108153515Skan } 4109216695Skib if (obj->vertab[verndx].hash != req->ventry->hash || 4110216695Skib strcmp(obj->vertab[verndx].name, req->ventry->name)) { 4111234840Skib /* 4112234840Skib * Version does not match. Look if this is a 4113234840Skib * global symbol and if it is not hidden. If 4114234840Skib * global symbol (verndx < 2) is available, 4115234840Skib * use it. Do not return symbol if we are 4116234840Skib * called by dlvsym, because dlvsym looks for 4117234840Skib * a specific version and default one is not 4118234840Skib * what dlvsym wants. 4119234840Skib */ 4120234840Skib if ((req->flags & SYMLOOK_DLSYM) || 4121234840Skib (verndx >= VER_NDX_GIVEN) || 4122234840Skib (obj->versyms[symnum] & VER_NDX_HIDDEN)) 4123234840Skib return (false); 4124153515Skan } 4125153515Skan } 4126234840Skib result->sym_out = symp; 4127234840Skib return (true); 412838739Sjdp} 412938739Sjdp 4130234841Skib/* 4131234841Skib * Search for symbol using SysV hash function. 4132234841Skib * obj->buckets is known not to be NULL at this point; the test for this was 4133234841Skib * performed with the obj->valid_hash_sysv assignment. 4134234841Skib */ 4135234840Skibstatic int 4136234841Skibsymlook_obj1_sysv(SymLook *req, const Obj_Entry *obj) 4137234840Skib{ 4138234840Skib unsigned long symnum; 4139234840Skib Sym_Match_Result matchres; 4140234840Skib 4141234840Skib matchres.sym_out = NULL; 4142234840Skib matchres.vsymp = NULL; 4143234840Skib matchres.vcount = 0; 4144234840Skib 4145234840Skib for (symnum = obj->buckets[req->hash % obj->nbuckets]; 4146234840Skib symnum != STN_UNDEF; symnum = obj->chains[symnum]) { 4147234840Skib if (symnum >= obj->nchains) 4148234840Skib return (ESRCH); /* Bad object */ 4149234840Skib 4150234840Skib if (matched_symbol(req, obj, &matchres, symnum)) { 4151234840Skib req->sym_out = matchres.sym_out; 4152234840Skib req->defobj_out = obj; 4153234840Skib return (0); 4154234840Skib } 4155234840Skib } 4156234840Skib if (matchres.vcount == 1) { 4157234840Skib req->sym_out = matchres.vsymp; 4158234840Skib req->defobj_out = obj; 4159234840Skib return (0); 4160234840Skib } 4161234840Skib return (ESRCH); 4162234840Skib} 4163234840Skib 4164234841Skib/* Search for symbol using GNU hash function */ 4165234841Skibstatic int 4166234841Skibsymlook_obj1_gnu(SymLook *req, const Obj_Entry *obj) 4167234841Skib{ 4168234841Skib Elf_Addr bloom_word; 4169234841Skib const Elf32_Word *hashval; 4170234841Skib Elf32_Word bucket; 4171234841Skib Sym_Match_Result matchres; 4172234841Skib unsigned int h1, h2; 4173234841Skib unsigned long symnum; 4174234841Skib 4175234841Skib matchres.sym_out = NULL; 4176234841Skib matchres.vsymp = NULL; 4177234841Skib matchres.vcount = 0; 4178234841Skib 4179234841Skib /* Pick right bitmask word from Bloom filter array */ 4180234841Skib bloom_word = obj->bloom_gnu[(req->hash_gnu / __ELF_WORD_SIZE) & 4181234841Skib obj->maskwords_bm_gnu]; 4182234841Skib 4183234841Skib /* Calculate modulus word size of gnu hash and its derivative */ 4184234841Skib h1 = req->hash_gnu & (__ELF_WORD_SIZE - 1); 4185234841Skib h2 = ((req->hash_gnu >> obj->shift2_gnu) & (__ELF_WORD_SIZE - 1)); 4186234841Skib 4187234841Skib /* Filter out the "definitely not in set" queries */ 4188234841Skib if (((bloom_word >> h1) & (bloom_word >> h2) & 1) == 0) 4189234841Skib return (ESRCH); 4190234841Skib 4191234841Skib /* Locate hash chain and corresponding value element*/ 4192234841Skib bucket = obj->buckets_gnu[req->hash_gnu % obj->nbuckets_gnu]; 4193234841Skib if (bucket == 0) 4194234841Skib return (ESRCH); 4195234841Skib hashval = &obj->chain_zero_gnu[bucket]; 4196234841Skib do { 4197234841Skib if (((*hashval ^ req->hash_gnu) >> 1) == 0) { 4198234841Skib symnum = hashval - obj->chain_zero_gnu; 4199234841Skib if (matched_symbol(req, obj, &matchres, symnum)) { 4200234841Skib req->sym_out = matchres.sym_out; 4201234841Skib req->defobj_out = obj; 4202234841Skib return (0); 4203234841Skib } 4204234841Skib } 4205234841Skib } while ((*hashval++ & 1) == 0); 4206234841Skib if (matchres.vcount == 1) { 4207234841Skib req->sym_out = matchres.vsymp; 4208234841Skib req->defobj_out = obj; 4209234841Skib return (0); 4210234841Skib } 4211234841Skib return (ESRCH); 4212234841Skib} 4213234841Skib 421438739Sjdpstatic void 421538739Sjdptrace_loaded_objects(Obj_Entry *obj) 421638739Sjdp{ 421790755Sobrien char *fmt1, *fmt2, *fmt, *main_local, *list_containers; 421835574Sdfr int c; 421935574Sdfr 4220127250Speter if ((main_local = getenv(LD_ "TRACE_LOADED_OBJECTS_PROGNAME")) == NULL) 422135574Sdfr main_local = ""; 422235574Sdfr 4223127250Speter if ((fmt1 = getenv(LD_ "TRACE_LOADED_OBJECTS_FMT1")) == NULL) 422435574Sdfr fmt1 = "\t%o => %p (%x)\n"; 422535574Sdfr 4226127250Speter if ((fmt2 = getenv(LD_ "TRACE_LOADED_OBJECTS_FMT2")) == NULL) 422735574Sdfr fmt2 = "\t%o (%x)\n"; 422835574Sdfr 4229127250Speter list_containers = getenv(LD_ "TRACE_LOADED_OBJECTS_ALL"); 423090755Sobrien 4231304454Skib for (; obj != NULL; obj = TAILQ_NEXT(obj, next)) { 423235574Sdfr Needed_Entry *needed; 423335574Sdfr char *name, *path; 423435574Sdfr bool is_lib; 423535574Sdfr 4236296727Skib if (obj->marker) 4237296727Skib continue; 423890755Sobrien if (list_containers && obj->needed != NULL) 4239225152Skib rtld_printf("%s:\n", obj->path); 424035574Sdfr for (needed = obj->needed; needed; needed = needed->next) { 424138740Sjdp if (needed->obj != NULL) { 424290755Sobrien if (needed->obj->traced && !list_containers) 424338740Sjdp continue; 424438740Sjdp needed->obj->traced = true; 424538740Sjdp path = needed->obj->path; 424638740Sjdp } else 424738740Sjdp path = "not found"; 424838740Sjdp 424935574Sdfr name = (char *)obj->strtab + needed->name; 425038740Sjdp is_lib = strncmp(name, "lib", 3) == 0; /* XXX - bogus */ 425135574Sdfr 425235574Sdfr fmt = is_lib ? fmt1 : fmt2; 425335574Sdfr while ((c = *fmt++) != '\0') { 425435574Sdfr switch (c) { 425535574Sdfr default: 4256225152Skib rtld_putchar(c); 425735574Sdfr continue; 425835574Sdfr case '\\': 425935574Sdfr switch (c = *fmt) { 426035574Sdfr case '\0': 426135574Sdfr continue; 426235574Sdfr case 'n': 4263225152Skib rtld_putchar('\n'); 426435574Sdfr break; 426535574Sdfr case 't': 4266225152Skib rtld_putchar('\t'); 426735574Sdfr break; 426835574Sdfr } 426935574Sdfr break; 427035574Sdfr case '%': 427135574Sdfr switch (c = *fmt) { 427235574Sdfr case '\0': 427335574Sdfr continue; 427435574Sdfr case '%': 427535574Sdfr default: 4276225152Skib rtld_putchar(c); 427735574Sdfr break; 427835574Sdfr case 'A': 4279225152Skib rtld_putstr(main_local); 428035574Sdfr break; 428135574Sdfr case 'a': 4282225152Skib rtld_putstr(obj_main->path); 428335574Sdfr break; 428435574Sdfr case 'o': 4285225152Skib rtld_putstr(name); 428635574Sdfr break; 428735574Sdfr#if 0 428835574Sdfr case 'm': 4289225152Skib rtld_printf("%d", sodp->sod_major); 429035574Sdfr break; 429135574Sdfr case 'n': 4292225152Skib rtld_printf("%d", sodp->sod_minor); 429335574Sdfr break; 429435574Sdfr#endif 429535574Sdfr case 'p': 4296225152Skib rtld_putstr(path); 429735574Sdfr break; 429835574Sdfr case 'x': 4299225152Skib rtld_printf("%p", needed->obj ? needed->obj->mapbase : 4300225152Skib 0); 430135574Sdfr break; 430235574Sdfr } 430335574Sdfr break; 430435574Sdfr } 430535574Sdfr ++fmt; 430635574Sdfr } 430735574Sdfr } 430835574Sdfr } 430935574Sdfr} 431038739Sjdp 431150608Sjdp/* 431255687Sjdp * Unload a dlopened object and its dependencies from memory and from 431355687Sjdp * our data structures. It is assumed that the DAG rooted in the 431455687Sjdp * object has already been unreferenced, and that the object has a 431555687Sjdp * reference count of 0. 431650608Sjdp */ 431738739Sjdpstatic void 431855687Sjdpunload_object(Obj_Entry *root) 431948708Sjdp{ 4320296727Skib Obj_Entry *obj, *obj1; 432148708Sjdp 4322296727Skib assert(root->refcount == 0); 432348708Sjdp 4324296727Skib /* 4325296727Skib * Pass over the DAG removing unreferenced objects from 4326296727Skib * appropriate lists. 4327296727Skib */ 4328296727Skib unlink_object(root); 4329111054Skan 4330296727Skib /* Unmap all objects that are no longer referenced. */ 4331296727Skib TAILQ_FOREACH_SAFE(obj, &obj_list, next, obj1) { 4332296727Skib if (obj->marker || obj->refcount != 0) 4333296727Skib continue; 4334296727Skib LD_UTRACE(UTRACE_UNLOAD_OBJECT, obj, obj->mapbase, 4335296727Skib obj->mapsize, 0, obj->path); 4336296727Skib dbg("unloading \"%s\"", obj->path); 4337296727Skib unload_filtees(root); 4338296727Skib munmap(obj->mapbase, obj->mapsize); 4339296727Skib linkmap_delete(obj); 4340296727Skib TAILQ_REMOVE(&obj_list, obj, next); 4341296727Skib obj_count--; 4342296727Skib obj_free(obj); 4343296727Skib } 434448708Sjdp} 434548708Sjdp 434648708Sjdpstatic void 4347111054Skanunlink_object(Obj_Entry *root) 434838739Sjdp{ 4349110659Skan Objlist_Entry *elm; 435050096Sjdp 4351110659Skan if (root->refcount == 0) { 4352110659Skan /* Remove the object from the RTLD_GLOBAL list. */ 4353110659Skan objlist_remove(&list_global, root); 4354110659Skan 4355110659Skan /* Remove the object from all objects' DAG lists. */ 4356153515Skan STAILQ_FOREACH(elm, &root->dagmembers, link) { 4357110659Skan objlist_remove(&elm->obj->dldags, root); 4358114826Skan if (elm->obj != root) 4359114826Skan unlink_object(elm->obj); 4360114826Skan } 4361110659Skan } 4362114826Skan} 4363111054Skan 4364114826Skanstatic void 4365114826Skanref_dag(Obj_Entry *root) 4366114826Skan{ 4367114826Skan Objlist_Entry *elm; 4368114826Skan 4369214777Skib assert(root->dag_inited); 4370153515Skan STAILQ_FOREACH(elm, &root->dagmembers, link) 4371114826Skan elm->obj->refcount++; 437238739Sjdp} 4373111054Skan 4374111054Skanstatic void 4375111054Skanunref_dag(Obj_Entry *root) 4376111054Skan{ 4377114826Skan Objlist_Entry *elm; 4378111054Skan 4379214777Skib assert(root->dag_inited); 4380153515Skan STAILQ_FOREACH(elm, &root->dagmembers, link) 4381114826Skan elm->obj->refcount--; 4382111054Skan} 4383115396Skan 4384133063Sdfr/* 4385133063Sdfr * Common code for MD __tls_get_addr(). 4386133063Sdfr */ 4387232777Skibstatic void *tls_get_addr_slow(Elf_Addr **, int, size_t) __noinline; 4388232777Skibstatic void * 4389232777Skibtls_get_addr_slow(Elf_Addr **dtvp, int index, size_t offset) 4390133063Sdfr{ 4391232777Skib Elf_Addr *newdtv, *dtv; 4392216695Skib RtldLockState lockstate; 4393232777Skib int to_copy; 4394115396Skan 4395232777Skib dtv = *dtvp; 4396133063Sdfr /* Check dtv generation in case new modules have arrived */ 4397133063Sdfr if (dtv[0] != tls_dtv_generation) { 4398216695Skib wlock_acquire(rtld_bind_lock, &lockstate); 4399233307Skib newdtv = xcalloc(tls_max_index + 2, sizeof(Elf_Addr)); 4400133063Sdfr to_copy = dtv[1]; 4401133063Sdfr if (to_copy > tls_max_index) 4402133063Sdfr to_copy = tls_max_index; 4403133063Sdfr memcpy(&newdtv[2], &dtv[2], to_copy * sizeof(Elf_Addr)); 4404133063Sdfr newdtv[0] = tls_dtv_generation; 4405133063Sdfr newdtv[1] = tls_max_index; 4406133063Sdfr free(dtv); 4407216695Skib lock_release(rtld_bind_lock, &lockstate); 4408225582Skib dtv = *dtvp = newdtv; 4409133063Sdfr } 4410133063Sdfr 4411133063Sdfr /* Dynamically allocate module TLS if necessary */ 4412232777Skib if (dtv[index + 1] == 0) { 4413143893Sdavidxu /* Signal safe, wlock will block out signals. */ 4414232777Skib wlock_acquire(rtld_bind_lock, &lockstate); 4415143893Sdavidxu if (!dtv[index + 1]) 4416143893Sdavidxu dtv[index + 1] = (Elf_Addr)allocate_module_tls(index); 4417216695Skib lock_release(rtld_bind_lock, &lockstate); 4418143893Sdavidxu } 4419232777Skib return ((void *)(dtv[index + 1] + offset)); 4420133063Sdfr} 4421133063Sdfr 4422232777Skibvoid * 4423232777Skibtls_get_addr_common(Elf_Addr **dtvp, int index, size_t offset) 4424232777Skib{ 4425232777Skib Elf_Addr *dtv; 4426232777Skib 4427232777Skib dtv = *dtvp; 4428232777Skib /* Check dtv generation in case new modules have arrived */ 4429232777Skib if (__predict_true(dtv[0] == tls_dtv_generation && 4430232777Skib dtv[index + 1] != 0)) 4431232777Skib return ((void *)(dtv[index + 1] + offset)); 4432232777Skib return (tls_get_addr_slow(dtvp, index, offset)); 4433232777Skib} 4434232777Skib 4435231618Sgonzo#if defined(__arm__) || defined(__ia64__) || defined(__mips__) || defined(__powerpc__) 4436133063Sdfr 4437133063Sdfr/* 4438133063Sdfr * Allocate Static TLS using the Variant I method. 4439133063Sdfr */ 4440133063Sdfrvoid * 4441161800Smarcelallocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcbsize, size_t tcbalign) 4442133063Sdfr{ 4443133063Sdfr Obj_Entry *obj; 4444161800Smarcel char *tcb; 4445161800Smarcel Elf_Addr **tls; 4446161800Smarcel Elf_Addr *dtv; 4447133063Sdfr Elf_Addr addr; 4448133063Sdfr int i; 4449133063Sdfr 4450161800Smarcel if (oldtcb != NULL && tcbsize == TLS_TCB_SIZE) 4451161800Smarcel return (oldtcb); 4452133063Sdfr 4453161800Smarcel assert(tcbsize >= TLS_TCB_SIZE); 4454233307Skib tcb = xcalloc(1, tls_static_space - TLS_TCB_SIZE + tcbsize); 4455161800Smarcel tls = (Elf_Addr **)(tcb + tcbsize - TLS_TCB_SIZE); 4456133063Sdfr 4457161800Smarcel if (oldtcb != NULL) { 4458161800Smarcel memcpy(tls, oldtcb, tls_static_space); 4459161800Smarcel free(oldtcb); 4460133063Sdfr 4461161800Smarcel /* Adjust the DTV. */ 4462161800Smarcel dtv = tls[0]; 4463161800Smarcel for (i = 0; i < dtv[1]; i++) { 4464161800Smarcel if (dtv[i+2] >= (Elf_Addr)oldtcb && 4465161800Smarcel dtv[i+2] < (Elf_Addr)oldtcb + tls_static_space) { 4466161800Smarcel dtv[i+2] = dtv[i+2] - (Elf_Addr)oldtcb + (Elf_Addr)tls; 4467133063Sdfr } 4468133063Sdfr } 4469161800Smarcel } else { 4470233307Skib dtv = xcalloc(tls_max_index + 2, sizeof(Elf_Addr)); 4471161800Smarcel tls[0] = dtv; 4472161800Smarcel dtv[0] = tls_dtv_generation; 4473161800Smarcel dtv[1] = tls_max_index; 4474133063Sdfr 4475296727Skib for (obj = globallist_curr(objs); obj != NULL; 4476296727Skib obj = globallist_next(obj)) { 4477203947Smarcel if (obj->tlsoffset > 0) { 4478133063Sdfr addr = (Elf_Addr)tls + obj->tlsoffset; 4479203947Smarcel if (obj->tlsinitsize > 0) 4480203947Smarcel memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize); 4481203947Smarcel if (obj->tlssize > obj->tlsinitsize) 4482203947Smarcel memset((void*) (addr + obj->tlsinitsize), 0, 4483203947Smarcel obj->tlssize - obj->tlsinitsize); 4484133063Sdfr dtv[obj->tlsindex + 1] = addr; 4485133063Sdfr } 4486133063Sdfr } 4487133063Sdfr } 4488133063Sdfr 4489161800Smarcel return (tcb); 4490133063Sdfr} 4491133063Sdfr 4492133063Sdfrvoid 4493161800Smarcelfree_tls(void *tcb, size_t tcbsize, size_t tcbalign) 4494133063Sdfr{ 4495161800Smarcel Elf_Addr *dtv; 4496161800Smarcel Elf_Addr tlsstart, tlsend; 4497133063Sdfr int dtvsize, i; 4498133063Sdfr 4499161800Smarcel assert(tcbsize >= TLS_TCB_SIZE); 4500133063Sdfr 4501161800Smarcel tlsstart = (Elf_Addr)tcb + tcbsize - TLS_TCB_SIZE; 4502161800Smarcel tlsend = tlsstart + tls_static_space; 4503161800Smarcel 4504161800Smarcel dtv = *(Elf_Addr **)tlsstart; 4505133063Sdfr dtvsize = dtv[1]; 4506133063Sdfr for (i = 0; i < dtvsize; i++) { 4507161800Smarcel if (dtv[i+2] && (dtv[i+2] < tlsstart || dtv[i+2] >= tlsend)) { 4508161800Smarcel free((void*)dtv[i+2]); 4509133063Sdfr } 4510133063Sdfr } 4511161800Smarcel free(dtv); 4512161800Smarcel free(tcb); 4513133063Sdfr} 4514133063Sdfr 4515133063Sdfr#endif 4516133063Sdfr 4517231618Sgonzo#if defined(__i386__) || defined(__amd64__) || defined(__sparc64__) 4518133063Sdfr 4519133063Sdfr/* 4520133063Sdfr * Allocate Static TLS using the Variant II method. 4521133063Sdfr */ 4522133063Sdfrvoid * 4523133063Sdfrallocate_tls(Obj_Entry *objs, void *oldtls, size_t tcbsize, size_t tcbalign) 4524133063Sdfr{ 4525133063Sdfr Obj_Entry *obj; 4526259292Skib size_t size, ralign; 4527133063Sdfr char *tls; 4528133063Sdfr Elf_Addr *dtv, *olddtv; 4529133063Sdfr Elf_Addr segbase, oldsegbase, addr; 4530133063Sdfr int i; 4531133063Sdfr 4532259292Skib ralign = tcbalign; 4533259292Skib if (tls_static_max_align > ralign) 4534259292Skib ralign = tls_static_max_align; 4535259292Skib size = round(tls_static_space, ralign) + round(tcbsize, ralign); 4536133063Sdfr 4537133063Sdfr assert(tcbsize >= 2*sizeof(Elf_Addr)); 4538259292Skib tls = malloc_aligned(size, ralign); 4539233307Skib dtv = xcalloc(tls_max_index + 2, sizeof(Elf_Addr)); 4540133063Sdfr 4541259292Skib segbase = (Elf_Addr)(tls + round(tls_static_space, ralign)); 4542133063Sdfr ((Elf_Addr*)segbase)[0] = segbase; 4543133063Sdfr ((Elf_Addr*)segbase)[1] = (Elf_Addr) dtv; 4544133063Sdfr 4545133063Sdfr dtv[0] = tls_dtv_generation; 4546133063Sdfr dtv[1] = tls_max_index; 4547133063Sdfr 4548133063Sdfr if (oldtls) { 4549133063Sdfr /* 4550133063Sdfr * Copy the static TLS block over whole. 4551133063Sdfr */ 4552133063Sdfr oldsegbase = (Elf_Addr) oldtls; 4553133063Sdfr memcpy((void *)(segbase - tls_static_space), 4554133063Sdfr (const void *)(oldsegbase - tls_static_space), 4555133063Sdfr tls_static_space); 4556133063Sdfr 4557133063Sdfr /* 4558133063Sdfr * If any dynamic TLS blocks have been created tls_get_addr(), 4559133063Sdfr * move them over. 4560133063Sdfr */ 4561133063Sdfr olddtv = ((Elf_Addr**)oldsegbase)[1]; 4562133063Sdfr for (i = 0; i < olddtv[1]; i++) { 4563133063Sdfr if (olddtv[i+2] < oldsegbase - size || olddtv[i+2] > oldsegbase) { 4564133063Sdfr dtv[i+2] = olddtv[i+2]; 4565133063Sdfr olddtv[i+2] = 0; 4566133063Sdfr } 4567133063Sdfr } 4568133063Sdfr 4569133063Sdfr /* 4570133063Sdfr * We assume that this block was the one we created with 4571133063Sdfr * allocate_initial_tls(). 4572133063Sdfr */ 4573133063Sdfr free_tls(oldtls, 2*sizeof(Elf_Addr), sizeof(Elf_Addr)); 4574133063Sdfr } else { 4575304454Skib for (obj = objs; obj != NULL; obj = TAILQ_NEXT(obj, next)) { 4576296727Skib if (obj->marker || obj->tlsoffset == 0) 4577296727Skib continue; 4578133063Sdfr addr = segbase - obj->tlsoffset; 4579133063Sdfr memset((void*) (addr + obj->tlsinitsize), 4580133063Sdfr 0, obj->tlssize - obj->tlsinitsize); 4581133063Sdfr if (obj->tlsinit) 4582133063Sdfr memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize); 4583133063Sdfr dtv[obj->tlsindex + 1] = addr; 4584133063Sdfr } 4585133063Sdfr } 4586133063Sdfr 4587133063Sdfr return (void*) segbase; 4588133063Sdfr} 4589133063Sdfr 4590133063Sdfrvoid 4591133063Sdfrfree_tls(void *tls, size_t tcbsize, size_t tcbalign) 4592133063Sdfr{ 4593133063Sdfr Elf_Addr* dtv; 4594259292Skib size_t size, ralign; 4595133063Sdfr int dtvsize, i; 4596133063Sdfr Elf_Addr tlsstart, tlsend; 4597133063Sdfr 4598133063Sdfr /* 4599133063Sdfr * Figure out the size of the initial TLS block so that we can 4600133063Sdfr * find stuff which ___tls_get_addr() allocated dynamically. 4601133063Sdfr */ 4602259292Skib ralign = tcbalign; 4603259292Skib if (tls_static_max_align > ralign) 4604259292Skib ralign = tls_static_max_align; 4605259292Skib size = round(tls_static_space, ralign); 4606133063Sdfr 4607133063Sdfr dtv = ((Elf_Addr**)tls)[1]; 4608133063Sdfr dtvsize = dtv[1]; 4609133063Sdfr tlsend = (Elf_Addr) tls; 4610133063Sdfr tlsstart = tlsend - size; 4611133063Sdfr for (i = 0; i < dtvsize; i++) { 4612259292Skib if (dtv[i + 2] != 0 && (dtv[i + 2] < tlsstart || dtv[i + 2] > tlsend)) { 4613259292Skib free_aligned((void *)dtv[i + 2]); 4614133063Sdfr } 4615133063Sdfr } 4616133063Sdfr 4617259292Skib free_aligned((void *)tlsstart); 4618169276Sdavidxu free((void*) dtv); 4619133063Sdfr} 4620133063Sdfr 4621133063Sdfr#endif 4622133063Sdfr 4623133063Sdfr/* 4624133063Sdfr * Allocate TLS block for module with given index. 4625133063Sdfr */ 4626133063Sdfrvoid * 4627133063Sdfrallocate_module_tls(int index) 4628133063Sdfr{ 4629133063Sdfr Obj_Entry* obj; 4630133063Sdfr char* p; 4631133063Sdfr 4632296727Skib TAILQ_FOREACH(obj, &obj_list, next) { 4633296727Skib if (obj->marker) 4634296727Skib continue; 4635133063Sdfr if (obj->tlsindex == index) 4636133063Sdfr break; 4637133063Sdfr } 4638133063Sdfr if (!obj) { 4639133063Sdfr _rtld_error("Can't find module with TLS index %d", index); 4640282118Semaste rtld_die(); 4641133063Sdfr } 4642133063Sdfr 4643259292Skib p = malloc_aligned(obj->tlssize, obj->tlsalign); 4644133063Sdfr memcpy(p, obj->tlsinit, obj->tlsinitsize); 4645133063Sdfr memset(p + obj->tlsinitsize, 0, obj->tlssize - obj->tlsinitsize); 4646133063Sdfr 4647133063Sdfr return p; 4648133063Sdfr} 4649133063Sdfr 4650133063Sdfrbool 4651133063Sdfrallocate_tls_offset(Obj_Entry *obj) 4652133063Sdfr{ 4653133063Sdfr size_t off; 4654133063Sdfr 4655133063Sdfr if (obj->tls_done) 4656133063Sdfr return true; 4657133063Sdfr 4658133063Sdfr if (obj->tlssize == 0) { 4659133063Sdfr obj->tls_done = true; 4660133063Sdfr return true; 4661133063Sdfr } 4662133063Sdfr 4663287560Sandrew if (tls_last_offset == 0) 4664133063Sdfr off = calculate_first_tls_offset(obj->tlssize, obj->tlsalign); 4665133063Sdfr else 4666133063Sdfr off = calculate_tls_offset(tls_last_offset, tls_last_size, 4667133063Sdfr obj->tlssize, obj->tlsalign); 4668133063Sdfr 4669133063Sdfr /* 4670133063Sdfr * If we have already fixed the size of the static TLS block, we 4671133063Sdfr * must stay within that size. When allocating the static TLS, we 4672133063Sdfr * leave a small amount of space spare to be used for dynamically 4673133063Sdfr * loading modules which use static TLS. 4674133063Sdfr */ 4675259292Skib if (tls_static_space != 0) { 4676133063Sdfr if (calculate_tls_end(off, obj->tlssize) > tls_static_space) 4677133063Sdfr return false; 4678259292Skib } else if (obj->tlsalign > tls_static_max_align) { 4679259292Skib tls_static_max_align = obj->tlsalign; 4680133063Sdfr } 4681133063Sdfr 4682133063Sdfr tls_last_offset = obj->tlsoffset = off; 4683133063Sdfr tls_last_size = obj->tlssize; 4684133063Sdfr obj->tls_done = true; 4685133063Sdfr 4686133063Sdfr return true; 4687133063Sdfr} 4688133063Sdfr 4689142645Sdfrvoid 4690142645Sdfrfree_tls_offset(Obj_Entry *obj) 4691142645Sdfr{ 4692203947Smarcel 4693142645Sdfr /* 4694142645Sdfr * If we were the last thing to allocate out of the static TLS 4695142645Sdfr * block, we give our space back to the 'allocator'. This is a 4696142645Sdfr * simplistic workaround to allow libGL.so.1 to be loaded and 4697203947Smarcel * unloaded multiple times. 4698142645Sdfr */ 4699142645Sdfr if (calculate_tls_end(obj->tlsoffset, obj->tlssize) 4700142645Sdfr == calculate_tls_end(tls_last_offset, tls_last_size)) { 4701142645Sdfr tls_last_offset -= obj->tlssize; 4702142645Sdfr tls_last_size = 0; 4703142645Sdfr } 4704142645Sdfr} 4705142645Sdfr 4706133063Sdfrvoid * 4707133063Sdfr_rtld_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign) 4708133063Sdfr{ 4709143893Sdavidxu void *ret; 4710216695Skib RtldLockState lockstate; 4711143893Sdavidxu 4712216695Skib wlock_acquire(rtld_bind_lock, &lockstate); 4713296727Skib ret = allocate_tls(globallist_curr(TAILQ_FIRST(&obj_list)), oldtls, 4714296727Skib tcbsize, tcbalign); 4715216695Skib lock_release(rtld_bind_lock, &lockstate); 4716143893Sdavidxu return (ret); 4717133063Sdfr} 4718133063Sdfr 4719133063Sdfrvoid 4720133063Sdfr_rtld_free_tls(void *tcb, size_t tcbsize, size_t tcbalign) 4721133063Sdfr{ 4722216695Skib RtldLockState lockstate; 4723143893Sdavidxu 4724216695Skib wlock_acquire(rtld_bind_lock, &lockstate); 4725133063Sdfr free_tls(tcb, tcbsize, tcbalign); 4726216695Skib lock_release(rtld_bind_lock, &lockstate); 4727133063Sdfr} 4728153515Skan 4729153515Skanstatic void 4730153515Skanobject_add_name(Obj_Entry *obj, const char *name) 4731153515Skan{ 4732153515Skan Name_Entry *entry; 4733153515Skan size_t len; 4734153515Skan 4735153515Skan len = strlen(name); 4736153515Skan entry = malloc(sizeof(Name_Entry) + len); 4737153515Skan 4738153515Skan if (entry != NULL) { 4739153515Skan strcpy(entry->name, name); 4740153515Skan STAILQ_INSERT_TAIL(&obj->names, entry, link); 4741153515Skan } 4742153515Skan} 4743153515Skan 4744153515Skanstatic int 4745153515Skanobject_match_name(const Obj_Entry *obj, const char *name) 4746153515Skan{ 4747153515Skan Name_Entry *entry; 4748153515Skan 4749153515Skan STAILQ_FOREACH(entry, &obj->names, link) { 4750153515Skan if (strcmp(name, entry->name) == 0) 4751153515Skan return (1); 4752153515Skan } 4753153515Skan return (0); 4754153515Skan} 4755153515Skan 4756153515Skanstatic Obj_Entry * 4757153515Skanlocate_dependency(const Obj_Entry *obj, const char *name) 4758153515Skan{ 4759153515Skan const Objlist_Entry *entry; 4760153515Skan const Needed_Entry *needed; 4761153515Skan 4762153515Skan STAILQ_FOREACH(entry, &list_main, link) { 4763153515Skan if (object_match_name(entry->obj, name)) 4764153515Skan return entry->obj; 4765153515Skan } 4766153515Skan 4767153515Skan for (needed = obj->needed; needed != NULL; needed = needed->next) { 4768218098Skib if (strcmp(obj->strtab + needed->name, name) == 0 || 4769218098Skib (needed->obj != NULL && object_match_name(needed->obj, name))) { 4770218098Skib /* 4771218098Skib * If there is DT_NEEDED for the name we are looking for, 4772218098Skib * we are all set. Note that object might not be found if 4773218098Skib * dependency was not loaded yet, so the function can 4774218098Skib * return NULL here. This is expected and handled 4775218099Skib * properly by the caller. 4776218098Skib */ 4777218098Skib return (needed->obj); 4778218098Skib } 4779153515Skan } 4780209558Snwhitehorn _rtld_error("%s: Unexpected inconsistency: dependency %s not found", 4781209558Snwhitehorn obj->path, name); 4782282118Semaste rtld_die(); 4783153515Skan} 4784153515Skan 4785153515Skanstatic int 4786153515Skancheck_object_provided_version(Obj_Entry *refobj, const Obj_Entry *depobj, 4787153515Skan const Elf_Vernaux *vna) 4788153515Skan{ 4789153515Skan const Elf_Verdef *vd; 4790153515Skan const char *vername; 4791153515Skan 4792153515Skan vername = refobj->strtab + vna->vna_name; 4793153515Skan vd = depobj->verdef; 4794153515Skan if (vd == NULL) { 4795153703Skan _rtld_error("%s: version %s required by %s not defined", 4796153703Skan depobj->path, vername, refobj->path); 4797153515Skan return (-1); 4798153515Skan } 4799153515Skan for (;;) { 4800153515Skan if (vd->vd_version != VER_DEF_CURRENT) { 4801153703Skan _rtld_error("%s: Unsupported version %d of Elf_Verdef entry", 4802153515Skan depobj->path, vd->vd_version); 4803153515Skan return (-1); 4804153515Skan } 4805153515Skan if (vna->vna_hash == vd->vd_hash) { 4806153515Skan const Elf_Verdaux *aux = (const Elf_Verdaux *) 4807153515Skan ((char *)vd + vd->vd_aux); 4808153515Skan if (strcmp(vername, depobj->strtab + aux->vda_name) == 0) 4809153515Skan return (0); 4810153515Skan } 4811153515Skan if (vd->vd_next == 0) 4812153515Skan break; 4813153515Skan vd = (const Elf_Verdef *) ((char *)vd + vd->vd_next); 4814153515Skan } 4815153515Skan if (vna->vna_flags & VER_FLG_WEAK) 4816153515Skan return (0); 4817153703Skan _rtld_error("%s: version %s required by %s not found", 4818153703Skan depobj->path, vername, refobj->path); 4819153515Skan return (-1); 4820153515Skan} 4821153515Skan 4822153515Skanstatic int 4823153515Skanrtld_verify_object_versions(Obj_Entry *obj) 4824153515Skan{ 4825153515Skan const Elf_Verneed *vn; 4826153515Skan const Elf_Verdef *vd; 4827153515Skan const Elf_Verdaux *vda; 4828153515Skan const Elf_Vernaux *vna; 4829153515Skan const Obj_Entry *depobj; 4830153515Skan int maxvernum, vernum; 4831153515Skan 4832233546Skib if (obj->ver_checked) 4833233546Skib return (0); 4834233546Skib obj->ver_checked = true; 4835233546Skib 4836153515Skan maxvernum = 0; 4837153515Skan /* 4838153515Skan * Walk over defined and required version records and figure out 4839153515Skan * max index used by any of them. Do very basic sanity checking 4840153515Skan * while there. 4841153515Skan */ 4842153515Skan vn = obj->verneed; 4843153515Skan while (vn != NULL) { 4844153515Skan if (vn->vn_version != VER_NEED_CURRENT) { 4845153703Skan _rtld_error("%s: Unsupported version %d of Elf_Verneed entry", 4846153515Skan obj->path, vn->vn_version); 4847153515Skan return (-1); 4848153515Skan } 4849153515Skan vna = (const Elf_Vernaux *) ((char *)vn + vn->vn_aux); 4850153515Skan for (;;) { 4851153515Skan vernum = VER_NEED_IDX(vna->vna_other); 4852153515Skan if (vernum > maxvernum) 4853153515Skan maxvernum = vernum; 4854153515Skan if (vna->vna_next == 0) 4855153515Skan break; 4856153515Skan vna = (const Elf_Vernaux *) ((char *)vna + vna->vna_next); 4857153515Skan } 4858153515Skan if (vn->vn_next == 0) 4859153515Skan break; 4860153515Skan vn = (const Elf_Verneed *) ((char *)vn + vn->vn_next); 4861153515Skan } 4862153515Skan 4863153515Skan vd = obj->verdef; 4864153515Skan while (vd != NULL) { 4865153515Skan if (vd->vd_version != VER_DEF_CURRENT) { 4866153703Skan _rtld_error("%s: Unsupported version %d of Elf_Verdef entry", 4867153703Skan obj->path, vd->vd_version); 4868153515Skan return (-1); 4869153515Skan } 4870153515Skan vernum = VER_DEF_IDX(vd->vd_ndx); 4871153515Skan if (vernum > maxvernum) 4872153515Skan maxvernum = vernum; 4873153515Skan if (vd->vd_next == 0) 4874153515Skan break; 4875153515Skan vd = (const Elf_Verdef *) ((char *)vd + vd->vd_next); 4876153515Skan } 4877153515Skan 4878153515Skan if (maxvernum == 0) 4879153515Skan return (0); 4880153515Skan 4881153515Skan /* 4882153515Skan * Store version information in array indexable by version index. 4883153515Skan * Verify that object version requirements are satisfied along the 4884153515Skan * way. 4885153515Skan */ 4886153515Skan obj->vernum = maxvernum + 1; 4887233307Skib obj->vertab = xcalloc(obj->vernum, sizeof(Ver_Entry)); 4888153515Skan 4889153515Skan vd = obj->verdef; 4890153515Skan while (vd != NULL) { 4891153515Skan if ((vd->vd_flags & VER_FLG_BASE) == 0) { 4892153515Skan vernum = VER_DEF_IDX(vd->vd_ndx); 4893153515Skan assert(vernum <= maxvernum); 4894153515Skan vda = (const Elf_Verdaux *)((char *)vd + vd->vd_aux); 4895153515Skan obj->vertab[vernum].hash = vd->vd_hash; 4896153515Skan obj->vertab[vernum].name = obj->strtab + vda->vda_name; 4897153515Skan obj->vertab[vernum].file = NULL; 4898153515Skan obj->vertab[vernum].flags = 0; 4899153515Skan } 4900153515Skan if (vd->vd_next == 0) 4901153515Skan break; 4902153515Skan vd = (const Elf_Verdef *) ((char *)vd + vd->vd_next); 4903153515Skan } 4904153515Skan 4905153515Skan vn = obj->verneed; 4906153515Skan while (vn != NULL) { 4907153515Skan depobj = locate_dependency(obj, obj->strtab + vn->vn_file); 4908218098Skib if (depobj == NULL) 4909218098Skib return (-1); 4910153515Skan vna = (const Elf_Vernaux *) ((char *)vn + vn->vn_aux); 4911153515Skan for (;;) { 4912153515Skan if (check_object_provided_version(obj, depobj, vna)) 4913153515Skan return (-1); 4914153515Skan vernum = VER_NEED_IDX(vna->vna_other); 4915153515Skan assert(vernum <= maxvernum); 4916153515Skan obj->vertab[vernum].hash = vna->vna_hash; 4917153515Skan obj->vertab[vernum].name = obj->strtab + vna->vna_name; 4918153515Skan obj->vertab[vernum].file = obj->strtab + vn->vn_file; 4919153515Skan obj->vertab[vernum].flags = (vna->vna_other & VER_NEED_HIDDEN) ? 4920153515Skan VER_INFO_HIDDEN : 0; 4921153515Skan if (vna->vna_next == 0) 4922153515Skan break; 4923153515Skan vna = (const Elf_Vernaux *) ((char *)vna + vna->vna_next); 4924153515Skan } 4925153515Skan if (vn->vn_next == 0) 4926153515Skan break; 4927153515Skan vn = (const Elf_Verneed *) ((char *)vn + vn->vn_next); 4928153515Skan } 4929153515Skan return 0; 4930153515Skan} 4931153515Skan 4932153515Skanstatic int 4933153515Skanrtld_verify_versions(const Objlist *objlist) 4934153515Skan{ 4935153515Skan Objlist_Entry *entry; 4936153515Skan int rc; 4937153515Skan 4938153515Skan rc = 0; 4939153515Skan STAILQ_FOREACH(entry, objlist, link) { 4940153515Skan /* 4941153515Skan * Skip dummy objects or objects that have their version requirements 4942153515Skan * already checked. 4943153515Skan */ 4944153515Skan if (entry->obj->strtab == NULL || entry->obj->vertab != NULL) 4945153515Skan continue; 4946153515Skan if (rtld_verify_object_versions(entry->obj) == -1) { 4947153515Skan rc = -1; 4948153515Skan if (ld_tracing == NULL) 4949153515Skan break; 4950153515Skan } 4951153515Skan } 4952168479Skan if (rc == 0 || ld_tracing != NULL) 4953168479Skan rc = rtld_verify_object_versions(&obj_rtld); 4954153515Skan return rc; 4955153515Skan} 4956153515Skan 4957153515Skanconst Ver_Entry * 4958153515Skanfetch_ventry(const Obj_Entry *obj, unsigned long symnum) 4959153515Skan{ 4960153515Skan Elf_Versym vernum; 4961153515Skan 4962153515Skan if (obj->vertab) { 4963153515Skan vernum = VER_NDX(obj->versyms[symnum]); 4964153515Skan if (vernum >= obj->vernum) { 4965153515Skan _rtld_error("%s: symbol %s has wrong verneed value %d", 4966153515Skan obj->path, obj->strtab + symnum, vernum); 4967153515Skan } else if (obj->vertab[vernum].hash != 0) { 4968153515Skan return &obj->vertab[vernum]; 4969153515Skan } 4970153515Skan } 4971153515Skan return NULL; 4972153515Skan} 4973211413Skib 4974217153Skibint 4975217153Skib_rtld_get_stack_prot(void) 4976217153Skib{ 4977217153Skib 4978217153Skib return (stack_prot); 4979217153Skib} 4980217153Skib 4981276908Skibint 4982276908Skib_rtld_is_dlopened(void *arg) 4983276908Skib{ 4984276908Skib Obj_Entry *obj; 4985276908Skib RtldLockState lockstate; 4986276908Skib int res; 4987276908Skib 4988276908Skib rlock_acquire(rtld_bind_lock, &lockstate); 4989276908Skib obj = dlcheck(arg); 4990276908Skib if (obj == NULL) 4991276908Skib obj = obj_from_addr(arg); 4992276908Skib if (obj == NULL) { 4993276908Skib _rtld_error("No shared object contains address"); 4994276908Skib lock_release(rtld_bind_lock, &lockstate); 4995276908Skib return (-1); 4996276908Skib } 4997276908Skib res = obj->dlopened ? 1 : 0; 4998276908Skib lock_release(rtld_bind_lock, &lockstate); 4999276908Skib return (res); 5000276908Skib} 5001276908Skib 5002312402Skibint 5003312402Skibobj_enforce_relro(Obj_Entry *obj) 5004312402Skib{ 5005312402Skib 5006312402Skib if (obj->relro_size > 0 && mprotect(obj->relro_page, obj->relro_size, 5007312402Skib PROT_READ) == -1) { 5008312402Skib _rtld_error("%s: Cannot enforce relro protection: %s", 5009312402Skib obj->path, rtld_strerror(errno)); 5010312402Skib return (-1); 5011312402Skib } 5012312402Skib return (0); 5013312402Skib} 5014312402Skib 5015217153Skibstatic void 5016217223Skibmap_stacks_exec(RtldLockState *lockstate) 5017217153Skib{ 5018217153Skib void (*thr_map_stacks_exec)(void); 5019217153Skib 5020217153Skib if ((max_stack_flags & PF_X) == 0 || (stack_prot & PROT_EXEC) != 0) 5021217153Skib return; 5022217153Skib thr_map_stacks_exec = (void (*)(void))(uintptr_t) 5023217223Skib get_program_var_addr("__pthread_map_stacks_exec", lockstate); 5024217153Skib if (thr_map_stacks_exec != NULL) { 5025217153Skib stack_prot |= PROT_EXEC; 5026217153Skib thr_map_stacks_exec(); 5027217153Skib } 5028217153Skib} 5029217153Skib 5030216695Skibvoid 5031216695Skibsymlook_init(SymLook *dst, const char *name) 5032216695Skib{ 5033216695Skib 5034216695Skib bzero(dst, sizeof(*dst)); 5035216695Skib dst->name = name; 5036216695Skib dst->hash = elf_hash(name); 5037234841Skib dst->hash_gnu = gnu_hash(name); 5038216695Skib} 5039216695Skib 5040216695Skibstatic void 5041216695Skibsymlook_init_from_req(SymLook *dst, const SymLook *src) 5042216695Skib{ 5043216695Skib 5044216695Skib dst->name = src->name; 5045216695Skib dst->hash = src->hash; 5046234841Skib dst->hash_gnu = src->hash_gnu; 5047216695Skib dst->ventry = src->ventry; 5048216695Skib dst->flags = src->flags; 5049216695Skib dst->defobj_out = NULL; 5050216695Skib dst->sym_out = NULL; 5051216695Skib dst->lockstate = src->lockstate; 5052216695Skib} 5053216695Skib 5054211706Skib/* 5055211706Skib * Overrides for libc_pic-provided functions. 5056211706Skib */ 5057211706Skib 5058211413Skibint 5059211413Skib__getosreldate(void) 5060211413Skib{ 5061211413Skib size_t len; 5062211413Skib int oid[2]; 5063211413Skib int error, osrel; 5064211413Skib 5065211413Skib if (osreldate != 0) 5066211413Skib return (osreldate); 5067211413Skib 5068211413Skib oid[0] = CTL_KERN; 5069211413Skib oid[1] = KERN_OSRELDATE; 5070211413Skib osrel = 0; 5071211413Skib len = sizeof(osrel); 5072211413Skib error = sysctl(oid, 2, &osrel, &len, NULL, 0); 5073211413Skib if (error == 0 && osrel > 0 && len == sizeof(osrel)) 5074211413Skib osreldate = osrel; 5075211413Skib return (osreldate); 5076211413Skib} 5077211706Skib 5078233430Skibvoid 5079233430Skibexit(int status) 5080233430Skib{ 5081233430Skib 5082233430Skib _exit(status); 5083233430Skib} 5084233430Skib 5085233430Skibvoid (*__cleanup)(void); 5086233430Skibint __isthreaded = 0; 5087233430Skibint _thread_autoinit_dummy_decl = 1; 5088233430Skib 5089211706Skib/* 5090211706Skib * No unresolved symbols for rtld. 5091211706Skib */ 5092211706Skibvoid 5093211706Skib__pthread_cxa_finalize(struct dl_phdr_info *a) 5094211706Skib{ 5095211706Skib} 5096232861Skib 5097232861Skibvoid 5098232861Skib__stack_chk_fail(void) 5099232861Skib{ 5100232861Skib 5101232861Skib _rtld_error("stack overflow detected; terminated"); 5102282118Semaste rtld_die(); 5103232861Skib} 5104233431Skib__weak_reference(__stack_chk_fail, __stack_chk_fail_local); 5105232861Skib 5106232861Skibvoid 5107232861Skib__chk_fail(void) 5108232861Skib{ 5109232861Skib 5110232861Skib _rtld_error("buffer overflow detected; terminated"); 5111282118Semaste rtld_die(); 5112232861Skib} 5113232974Skib 5114232974Skibconst char * 5115232974Skibrtld_strerror(int errnum) 5116232974Skib{ 5117232974Skib 5118232974Skib if (errnum < 0 || errnum >= sys_nerr) 5119232974Skib return ("Unknown error"); 5120232974Skib return (sys_errlist[errnum]); 5121232974Skib} 5122