1 /*- 2 * Copyright (c) 1998 John D. Polstra 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: src/lib/libc/gen/dlfcn.c 217154 2011-01-08 17:13:43Z kib $ 27 */ 28 29 #include <sys/mman.h> 30 #include <dlfcn.h> 31 #include <link.h> 32 #include <stddef.h> 33 #include <string.h> 34 #include "libc_private.h" 35 36 struct dl_phdr_info build_phdr_info(void); 37 void _rtld_thread_childfork(void); 38 void _rtld_thread_init(void *); 39 void _rtld_thread_postfork(void); 40 void _rtld_thread_prefork(void); 41 void _rtld_setthreaded(void); 42 43 extern char **environ; 44 45 static char sorry[] = "Service unavailable"; 46 47 /* 48 * For ELF, the dynamic linker directly resolves references to its 49 * services to functions inside the dynamic linker itself. These 50 * weak-symbol stubs are necessary so that "ld" won't complain about 51 * undefined symbols. The stubs are executed only when the program is 52 * linked statically, or when a given service isn't implemented in the 53 * dynamic linker. They must return an error if called, and they must 54 * be weak symbols so that the dynamic linker can override them. 55 */ 56 57 #pragma weak _rtld_error 58 void 59 _rtld_error(const char *fmt __unused, ...) 60 { 61 } 62 63 #pragma weak dladdr 64 int 65 dladdr(const void *addr __unused, Dl_info *dlip __unused) 66 { 67 _rtld_error(sorry); 68 return 0; 69 } 70 71 #pragma weak dlclose 72 int 73 dlclose(void *handle __unused) 74 { 75 _rtld_error(sorry); 76 return -1; 77 } 78 79 #pragma weak dlerror 80 char * 81 dlerror(void) 82 { 83 return sorry; 84 } 85 86 #pragma weak dlopen 87 void * 88 dlopen(const char *name __unused, int mode __unused) 89 { 90 _rtld_error(sorry); 91 return NULL; 92 } 93 94 #pragma weak dlsym 95 void * 96 dlsym(void *handle __unused, const char *name __unused) 97 { 98 _rtld_error(sorry); 99 return NULL; 100 } 101 102 #pragma weak dlfunc 103 dlfunc_t 104 dlfunc(void * handle __unused, const char * name __unused) 105 { 106 _rtld_error(sorry); 107 return NULL; 108 } 109 110 #pragma weak dlvsym 111 void * 112 dlvsym(void *handle __unused,const char *name __unused, 113 const char *version __unused) 114 { 115 _rtld_error(sorry); 116 return NULL; 117 } 118 119 #pragma weak _rtld_thread_init 120 void 121 _rtld_thread_init(void * li __unused) 122 { 123 _rtld_error(sorry); 124 } 125 126 #pragma weak dlinfo 127 int 128 dlinfo(void *handle __unused, int request __unused, void *p __unused) 129 { 130 _rtld_error(sorry); 131 return 0; 132 } 133 134 __dso_hidden struct dl_phdr_info 135 build_phdr_info(void) 136 { 137 struct dl_phdr_info phdr_info; 138 Elf_Addr *sp; 139 Elf_Auxinfo *aux, *auxp; 140 unsigned int i; 141 142 sp = (Elf_Addr *) environ; 143 while (*sp++ != 0) 144 ; 145 aux = (Elf_Auxinfo *) sp; 146 memset (&phdr_info, 0, sizeof(phdr_info)); 147 for (auxp = aux; auxp->a_type != AT_NULL; auxp++) { 148 switch (auxp->a_type) { 149 case AT_BASE: 150 phdr_info.dlpi_addr = (Elf_Addr) auxp->a_un.a_ptr; 151 break; 152 case AT_EXECPATH: 153 phdr_info.dlpi_name = (const char *) auxp->a_un.a_ptr; 154 break; 155 case AT_PHDR: 156 phdr_info.dlpi_phdr = (const Elf_Phdr *) auxp->a_un.a_ptr; 157 break; 158 case AT_PHNUM: 159 phdr_info.dlpi_phnum = (Elf_Half) auxp->a_un.a_val; 160 break; 161 } 162 } 163 164 for (i = 0; i < phdr_info.dlpi_phnum; i++) 165 if (phdr_info.dlpi_phdr[i].p_type == PT_TLS) { 166 phdr_info.dlpi_tls_modid = 1; 167 phdr_info.dlpi_tls_data = 168 (void*)phdr_info.dlpi_phdr[i].p_vaddr; 169 } 170 171 return (phdr_info); 172 } 173 174 #pragma weak dl_iterate_phdr 175 int 176 dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), 177 void *data) 178 { 179 static int seen = 0; 180 static struct dl_phdr_info phdr_info; 181 if (!seen) { 182 seen = 1; 183 phdr_info = build_phdr_info(); 184 } 185 186 return callback(&phdr_info, sizeof(phdr_info), data); 187 } 188 189 #pragma weak fdlopen 190 void * 191 fdlopen(int fd __unused, int mode __unused) 192 { 193 _rtld_error(sorry); 194 return NULL; 195 } 196 197 #pragma weak _rtld_addr_phdr 198 int 199 _rtld_addr_phdr(const void *addr __unused, 200 struct dl_phdr_info *phdr_info __unused) 201 { 202 203 return (0); 204 } 205 206 #pragma weak _rtld_get_stack_prot 207 int 208 _rtld_get_stack_prot(void) 209 { 210 return (PROT_EXEC | PROT_READ | PROT_WRITE); 211 } 212 213 #pragma weak _rtld_thread_prefork 214 void 215 _rtld_thread_prefork(void) 216 { 217 } 218 219 #pragma weak _rtld_thread_postfork 220 void 221 _rtld_thread_postfork(void) 222 { 223 } 224 225 #pragma weak _rtld_thread_childfork 226 void 227 _rtld_thread_childfork(void) 228 { 229 } 230 231 #pragma weak _rtld_setthreaded 232 void 233 _rtld_setthreaded(void) 234 { 235 } 236