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>
23 /* Darwin does not define the standard ELF
24 * dlopen/dlclose/dlsym/dlerror interface to shared libraries, so this
25 * is an attempt at a minimal wrapper to allow SBCL to work without
26 * external dependency on pogma's dlcompat library.
29 /* For now, there is no RTLD_GLOBAL emulation either. */
31 static char dl_self; /* I'm going to abuse this */
35 #define RTLD_GLOBAL 0x100
37 static int callback_count;
38 static struct mach_header* last_header;
40 void dlshim_image_callback(struct mach_header* ptr, unsigned long phooey)
46 int lib_path_count(void)
51 libpath = getenv("DYLD_LIBRARY_PATH");
54 for (i = 0; libpath[i] != '\0'; i++) {
55 if (libpath[i] == ':') count++;
61 const char* lib_path_prefixify(int index, const char* filename)
63 static char* retbuf = NULL;
67 retbuf = (char*) malloc(1024*sizeof(char));
72 libpath = getenv("DYLD_LIBRARY_PATH");
75 while (count != index && libpath[i] != '\0') {
76 if (libpath[i] == ':') count++;
80 while (libpath[i] != '\0' && libpath[i] != ':') {
86 if (li - fi + 1 > 1022 - strlen(filename)) {
87 retbuf = (char*) realloc(retbuf, (li - fi + 3 + strlen(filename))*sizeof(char));
89 memcpy(retbuf, libpath + fi, (li - fi + 1)*sizeof(char));
90 retbuf[li - fi + 1] = '/';
91 memcpy(retbuf + li - fi + 2, filename, strlen(filename) + 1);
98 void* dlopen(const char* filename, int flags)
100 static char has_callback = 0;
102 _dyld_register_func_for_add_image(dlshim_image_callback);
107 struct mach_header* img = NULL;
108 if (!img) img = NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
109 if (!img) img = NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR | NSADDIMAGE_OPTION_WITH_SEARCHING);
111 NSObjectFileImage fileImage;
114 if (NSCreateObjectFileImageFromFile(filename, &fileImage) == NSObjectFileImageSuccess) {
115 NSLinkModule(fileImage, filename, NSLINKMODULE_OPTION_BINDNOW | ((flags & RTLD_GLOBAL)?NSLINKMODULE_OPTION_PRIVATE:0) | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
116 if (callback_count && last_header) img = last_header;
120 NSObjectFileImage fileImage;
122 char* prefixfilename;
123 maxi = lib_path_count();
124 for (i = 0; i < maxi && !img; i++) {
125 prefixfilename = lib_path_prefixify(i, filename);
128 if (NSCreateObjectFileImageFromFile(prefixfilename, &fileImage) == NSObjectFileImageSuccess) {
129 NSLinkModule(fileImage, filename, NSLINKMODULE_OPTION_BINDNOW | ((flags & RTLD_GLOBAL)?NSLINKMODULE_OPTION_PRIVATE:0) | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
130 if (callback_count && last_header) img = last_header;
135 if (flags & RTLD_NOW) {
136 NSLookupSymbolInImage(img, "", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
138 if (NSIsSymbolNameDefinedInImage(img, "__init")) {
139 NSSymbol* initsymbol;
140 void (*initfunc) (void);
141 initsymbol = NSLookupSymbolInImage(img, "__init", 0);
142 initfunc = NSAddressOfSymbol(initsymbol);
150 const char* dlerror()
152 static char* errbuf = NULL;
156 NSLinkEditError(&a, &b, &c, &d);
158 errbuf = (char*) malloc(256*sizeof(char));
160 snprintf(errbuf, 255, "%s in %s: %d %d", c, d, a, b);
164 void* dlsym(void* handle, char* symbol)
166 if (handle == &dl_self) {
167 if (NSIsSymbolNameDefined(symbol)) {
169 retsym = NSLookupAndBindSymbol(symbol);
170 return NSAddressOfSymbol(retsym);
175 if (NSIsSymbolNameDefinedInImage(handle, symbol)) {
177 retsym = NSLookupSymbolInImage(handle, symbol, 0);
178 return NSAddressOfSymbol(retsym);
185 int dlclose(void *handle)
187 /* dlclose is not implemented, and never will be for dylibs.
188 * return -1 to signal an error; it's not used by SBCL anyhow */