2 * These functions emulate a small subset of the dlopen / dlsym
3 * functionality under Darwin's Mach-O dyld system.
7 * This software is part of the SBCL system. See the README file for
10 * This software is derived from the CMU CL system, which was
11 * written at Carnegie Mellon University and released into the
12 * public domain. The software is in the public domain and is
13 * provided with absolutely no warranty. See the COPYING and CREDITS
14 * files for more information.
18 #include <mach-o/dyld.h>
22 #include "darwin-dlshim.h"
24 /* Darwin does not define the standard ELF
25 * dlopen/dlclose/dlsym/dlerror interface to shared libraries, so this
26 * is an attempt at a minimal wrapper to allow SBCL to work without
27 * external dependency on pogma's dlcompat library.
30 /* For now, there is no RTLD_GLOBAL emulation either. */
32 static char dl_self; /* I'm going to abuse this */
34 static int callback_count;
35 static const struct mach_header* last_header;
38 #define DLOPEN_ERROR 2
40 static int last_error = 0;
43 dlshim_image_callback(const struct mach_header* ptr, intptr_t phooey)
55 libpath = getenv("DYLD_LIBRARY_PATH");
58 for (i = 0; libpath[i] != '\0'; i++) {
59 if (libpath[i] == ':') count++;
66 lib_path_prefixify(int index, const char* filename)
68 static char* retbuf = NULL;
72 retbuf = (char*) malloc(1024*sizeof(char));
77 libpath = getenv("DYLD_LIBRARY_PATH");
80 while (count != index && libpath[i] != '\0') {
81 if (libpath[i] == ':') count++;
85 while (libpath[i] != '\0' && libpath[i] != ':') {
91 if (li - fi + 1 > 1022 - strlen(filename)) {
93 (char*) realloc(retbuf, (li - fi + 3 + strlen(filename))*sizeof(char));
95 memcpy(retbuf, libpath + fi, (li - fi + 1)*sizeof(char));
96 retbuf[li - fi + 1] = '/';
97 memcpy(retbuf + li - fi + 2, filename, strlen(filename) + 1);
105 dlopen(const char* filename, int flags)
107 static char has_callback = 0;
109 _dyld_register_func_for_add_image(dlshim_image_callback);
114 const struct mach_header* img = NULL;
116 img = NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
118 img = NSAddImage(filename,
119 NSADDIMAGE_OPTION_RETURN_ON_ERROR |
120 NSADDIMAGE_OPTION_WITH_SEARCHING);
122 NSObjectFileImage fileImage;
125 if (NSCreateObjectFileImageFromFile(filename, &fileImage)
126 == NSObjectFileImageSuccess) {
127 NSLinkModule(fileImage, filename,
128 NSLINKMODULE_OPTION_BINDNOW |
129 ((flags & RTLD_GLOBAL)?NSLINKMODULE_OPTION_PRIVATE:0) |
130 NSLINKMODULE_OPTION_RETURN_ON_ERROR);
131 if (callback_count && last_header)
136 NSObjectFileImage fileImage;
138 const char* prefixfilename;
139 maxi = lib_path_count();
140 for (i = 0; i < maxi && !img; i++) {
141 prefixfilename = lib_path_prefixify(i, filename);
144 if (NSCreateObjectFileImageFromFile(prefixfilename, &fileImage)
145 == NSObjectFileImageSuccess) {
146 NSLinkModule(fileImage, filename,
147 NSLINKMODULE_OPTION_BINDNOW |
148 ((flags & RTLD_GLOBAL)?NSLINKMODULE_OPTION_PRIVATE:0) |
149 NSLINKMODULE_OPTION_RETURN_ON_ERROR);
150 if (callback_count && last_header)
156 if (flags & RTLD_NOW) {
157 NSLookupSymbolInImage(img, "",
158 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY |
159 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
161 if (NSIsSymbolNameDefinedInImage(img, "__init")) {
163 void (*initfunc) (void);
164 initsymbol = NSLookupSymbolInImage(img, "__init", 0);
165 initfunc = NSAddressOfSymbol(initsymbol);
169 last_error = DLOPEN_ERROR;
179 const char *fileName, *errorString;
183 NSLinkEditError(&c, &errorNumber, &fileName, &errorString);
184 /* The errorString obtained by the above is too verbose for
185 * our needs, so we just translate the errno.
187 * We also have simple fallbacks in case we've somehow lost
188 * the context before this point. */
190 result = strerror(errorNumber);
191 } else if (DLSYM_ERROR == last_error) {
192 result = "dlsym(3) failed";
193 } else if (DLOPEN_ERROR == last_error) {
194 result = "dlopen(3) failed";
203 dlsym(void* handle, char* symbol)
205 if (handle == &dl_self) {
206 if (NSIsSymbolNameDefined(symbol)) {
208 retsym = NSLookupAndBindSymbol(symbol);
209 return NSAddressOfSymbol(retsym);
211 last_error = DLSYM_ERROR;
215 if (NSIsSymbolNameDefinedInImage(handle, symbol)) {
217 retsym = NSLookupSymbolInImage(handle, symbol, 0);
218 return NSAddressOfSymbol(retsym);
220 last_error = DLSYM_ERROR;
227 dlclose(void *handle)
229 /* dlclose is not implemented, and never will be for dylibs.
230 * return -1 to signal an error; it's not used by SBCL anyhow */