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,v 1.6.2.1 2003/02/20 20:42:45 kan Exp $ 27 * $DragonFly: src/lib/libc/gen/dlfcn.c,v 1.2 2003/06/17 04:26:42 dillon Exp $ 28 */ 29 30 /* 31 * Linkage to services provided by the dynamic linker. These are 32 * implemented differently in ELF and a.out, because the dynamic 33 * linkers have different interfaces. 34 */ 35 36 #ifdef __ELF__ 37 38 #include <dlfcn.h> 39 #include <stddef.h> 40 41 static const char sorry[] = "Service unavailable"; 42 43 /* 44 * For ELF, the dynamic linker directly resolves references to its 45 * services to functions inside the dynamic linker itself. These 46 * weak-symbol stubs are necessary so that "ld" won't complain about 47 * undefined symbols. The stubs are executed only when the program is 48 * linked statically, or when a given service isn't implemented in the 49 * dynamic linker. They must return an error if called, and they must 50 * be weak symbols so that the dynamic linker can override them. 51 */ 52 53 #pragma weak _rtld_error 54 void 55 _rtld_error(const char *fmt, ...) 56 { 57 } 58 59 #pragma weak dladdr 60 int 61 dladdr(const void *addr, Dl_info *dlip) 62 { 63 _rtld_error(sorry); 64 return 0; 65 } 66 67 #pragma weak dlclose 68 int 69 dlclose(void *handle) 70 { 71 _rtld_error(sorry); 72 return -1; 73 } 74 75 #pragma weak dlerror 76 const char * 77 dlerror(void) 78 { 79 return sorry; 80 } 81 82 #pragma weak dllockinit 83 void 84 dllockinit(void *context, 85 void *(*lock_create)(void *context), 86 void (*rlock_acquire)(void *lock), 87 void (*wlock_acquire)(void *lock), 88 void (*lock_release)(void *lock), 89 void (*lock_destroy)(void *lock), 90 void (*context_destroy)(void *context)) 91 { 92 if (context_destroy != NULL) 93 context_destroy(context); 94 } 95 96 #pragma weak dlopen 97 void * 98 dlopen(const char *name, int mode) 99 { 100 _rtld_error(sorry); 101 return NULL; 102 } 103 104 #pragma weak dlsym 105 void * 106 dlsym(void *handle, const char *name) 107 { 108 _rtld_error(sorry); 109 return NULL; 110 } 111 112 #pragma weak dlinfo 113 int 114 dlinfo(void *handle, int request, void *p) 115 { 116 _rtld_error(sorry); 117 return NULL; 118 } 119 120 #else /* a.out format */ 121 122 #include <sys/types.h> 123 #include <nlist.h> /* XXX - Required by link.h */ 124 #include <dlfcn.h> 125 #include <link.h> 126 #include <stddef.h> 127 128 /* 129 * For a.out, entry to the dynamic linker is via these trampolines. 130 * They enter the dynamic linker through the ld_entry struct that was 131 * passed back from the dynamic linker at startup time. 132 */ 133 134 /* GCC is needed because we use its __builtin_return_address construct. */ 135 136 #ifndef __GNUC__ 137 #error "GCC is needed to compile this file" 138 #endif 139 140 /* 141 * These variables are set by code in crt0.o. For compatibility with 142 * old executables, they must be common, not extern. 143 */ 144 struct ld_entry *__ldso_entry; /* Entry points to dynamic linker */ 145 int __ldso_version; /* Dynamic linker version number */ 146 147 int 148 dladdr(const void *addr, Dl_info *dlip) 149 { 150 if (__ldso_entry == NULL || __ldso_version < LDSO_VERSION_HAS_DLADDR) 151 return 0; 152 return (__ldso_entry->dladdr)(addr, dlip); 153 } 154 155 int 156 dlclose(void *handle) 157 { 158 if (__ldso_entry == NULL) 159 return -1; 160 return (__ldso_entry->dlclose)(handle); 161 } 162 163 const char * 164 dlerror(void) 165 { 166 if (__ldso_entry == NULL) 167 return "Service unavailable"; 168 return (__ldso_entry->dlerror)(); 169 } 170 171 void * 172 dlopen(const char *name, int mode) 173 { 174 if (__ldso_entry == NULL) 175 return NULL; 176 return (__ldso_entry->dlopen)(name, mode); 177 } 178 179 void * 180 dlsym(void *handle, const char *name) 181 { 182 if (__ldso_entry == NULL) 183 return NULL; 184 if (__ldso_version >= LDSO_VERSION_HAS_DLSYM3) { 185 void *retaddr = __builtin_return_address(0); /* __GNUC__ only */ 186 return (__ldso_entry->dlsym3)(handle, name, retaddr); 187 } else 188 return (__ldso_entry->dlsym)(handle, name); 189 } 190 191 #endif /* __ELF__ */ 192