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 42 extern char **environ; 43 44 static char sorry[] = "Service unavailable"; 45 46 /* 47 * For ELF, the dynamic linker directly resolves references to its 48 * services to functions inside the dynamic linker itself. These 49 * weak-symbol stubs are necessary so that "ld" won't complain about 50 * undefined symbols. The stubs are executed only when the program is 51 * linked statically, or when a given service isn't implemented in the 52 * dynamic linker. They must return an error if called, and they must 53 * be weak symbols so that the dynamic linker can override them. 54 */ 55 56 #pragma weak _rtld_error 57 void 58 _rtld_error(const char *fmt __unused, ...) 59 { 60 } 61 62 #pragma weak dladdr 63 int 64 dladdr(const void *addr __unused, Dl_info *dlip __unused) 65 { 66 _rtld_error(sorry); 67 return 0; 68 } 69 70 #pragma weak dlclose 71 int 72 dlclose(void *handle __unused) 73 { 74 _rtld_error(sorry); 75 return -1; 76 } 77 78 #pragma weak dlerror 79 char * 80 dlerror(void) 81 { 82 return sorry; 83 } 84 85 #pragma weak dlopen 86 void * 87 dlopen(const char *name __unused, int mode __unused) 88 { 89 _rtld_error(sorry); 90 return NULL; 91 } 92 93 #pragma weak dlsym 94 void * 95 dlsym(void *handle __unused, const char *name __unused) 96 { 97 _rtld_error(sorry); 98 return NULL; 99 } 100 101 #pragma weak dlfunc 102 dlfunc_t 103 dlfunc(void * handle __unused, const char * name __unused) 104 { 105 _rtld_error(sorry); 106 return NULL; 107 } 108 109 #pragma weak dlvsym 110 void * 111 dlvsym(void *handle __unused,const char *name __unused, 112 const char *version __unused) 113 { 114 _rtld_error(sorry); 115 return NULL; 116 } 117 118 #pragma weak _rtld_thread_init 119 void 120 _rtld_thread_init(void * li __unused) 121 { 122 _rtld_error(sorry); 123 } 124 125 #pragma weak dlinfo 126 int 127 dlinfo(void *handle __unused, int request __unused, void *p __unused) 128 { 129 _rtld_error(sorry); 130 return 0; 131 } 132 133 __dso_hidden struct dl_phdr_info 134 build_phdr_info(void) 135 { 136 struct dl_phdr_info phdr_info; 137 Elf_Addr *sp; 138 Elf_Auxinfo *aux, *auxp; 139 unsigned int i; 140 141 sp = (Elf_Addr *) environ; 142 while (*sp++ != 0) 143 ; 144 aux = (Elf_Auxinfo *) sp; 145 memset (&phdr_info, 0, sizeof(phdr_info)); 146 for (auxp = aux; auxp->a_type != AT_NULL; auxp++) { 147 switch (auxp->a_type) { 148 case AT_BASE: 149 phdr_info.dlpi_addr = (Elf_Addr) auxp->a_un.a_ptr; 150 break; 151 case AT_EXECPATH: 152 phdr_info.dlpi_name = (const char *) auxp->a_un.a_ptr; 153 break; 154 case AT_PHDR: 155 phdr_info.dlpi_phdr = (const Elf_Phdr *) auxp->a_un.a_ptr; 156 break; 157 case AT_PHNUM: 158 phdr_info.dlpi_phnum = (Elf_Half) auxp->a_un.a_val; 159 break; 160 } 161 } 162 163 for (i = 0; i < phdr_info.dlpi_phnum; i++) 164 if (phdr_info.dlpi_phdr[i].p_type == PT_TLS) { 165 phdr_info.dlpi_tls_modid = 1; 166 phdr_info.dlpi_tls_data = 167 (void*)phdr_info.dlpi_phdr[i].p_vaddr; 168 } 169 170 return (phdr_info); 171 } 172 173 #pragma weak dl_iterate_phdr 174 int 175 dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), 176 void *data) 177 { 178 static int seen = 0; 179 static struct dl_phdr_info phdr_info; 180 if (!seen) { 181 seen = 1; 182 phdr_info = build_phdr_info(); 183 } 184 185 return callback(&phdr_info, sizeof(phdr_info), data); 186 } 187 188 #pragma weak fdlopen 189 void * 190 fdlopen(int fd __unused, int mode __unused) 191 { 192 _rtld_error(sorry); 193 return NULL; 194 } 195 196 #pragma weak _rtld_addr_phdr 197 int 198 _rtld_addr_phdr(const void *addr __unused, 199 struct dl_phdr_info *phdr_info __unused) 200 { 201 202 return (0); 203 } 204 205 #pragma weak _rtld_get_stack_prot 206 int 207 _rtld_get_stack_prot(void) 208 { 209 return (PROT_EXEC | PROT_READ | PROT_WRITE); 210 } 211 212 #pragma weak _rtld_thread_prefork 213 void 214 _rtld_thread_prefork(void) 215 { 216 } 217 218 #pragma weak _rtld_thread_postfork 219 void 220 _rtld_thread_postfork(void) 221 { 222 } 223 224 #pragma weak _rtld_thread_childfork 225 void 226 _rtld_thread_childfork(void) 227 { 228 } 229