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 "ppc-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 struct mach_header* last_header;
36 static int last_was_error = 0;
38 void dlshim_image_callback(struct mach_header* ptr, unsigned long phooey)
44 int lib_path_count(void)
49 libpath = getenv("DYLD_LIBRARY_PATH");
52 for (i = 0; libpath[i] != '\0'; i++) {
53 if (libpath[i] == ':') count++;
59 const char* lib_path_prefixify(int index, const char* filename)
61 static char* retbuf = NULL;
65 retbuf = (char*) malloc(1024*sizeof(char));
70 libpath = getenv("DYLD_LIBRARY_PATH");
73 while (count != index && libpath[i] != '\0') {
74 if (libpath[i] == ':') count++;
78 while (libpath[i] != '\0' && libpath[i] != ':') {
84 if (li - fi + 1 > 1022 - strlen(filename)) {
85 retbuf = (char*) realloc(retbuf, (li - fi + 3 + strlen(filename))*sizeof(char));
87 memcpy(retbuf, libpath + fi, (li - fi + 1)*sizeof(char));
88 retbuf[li - fi + 1] = '/';
89 memcpy(retbuf + li - fi + 2, filename, strlen(filename) + 1);
96 void* dlopen(const char* filename, int flags)
98 static char has_callback = 0;
100 _dyld_register_func_for_add_image(dlshim_image_callback);
105 struct mach_header* img = NULL;
106 if (!img) img = NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
107 if (!img) img = NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR | NSADDIMAGE_OPTION_WITH_SEARCHING);
109 NSObjectFileImage fileImage;
112 if (NSCreateObjectFileImageFromFile(filename, &fileImage) == NSObjectFileImageSuccess) {
113 NSLinkModule(fileImage, filename, NSLINKMODULE_OPTION_BINDNOW | ((flags & RTLD_GLOBAL)?NSLINKMODULE_OPTION_PRIVATE:0) | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
114 if (callback_count && last_header) img = last_header;
118 NSObjectFileImage fileImage;
120 char* prefixfilename;
121 maxi = lib_path_count();
122 for (i = 0; i < maxi && !img; i++) {
123 prefixfilename = lib_path_prefixify(i, filename);
126 if (NSCreateObjectFileImageFromFile(prefixfilename, &fileImage) == NSObjectFileImageSuccess) {
127 NSLinkModule(fileImage, filename, NSLINKMODULE_OPTION_BINDNOW | ((flags & RTLD_GLOBAL)?NSLINKMODULE_OPTION_PRIVATE:0) | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
128 if (callback_count && last_header) img = last_header;
133 if (flags & RTLD_NOW) {
134 NSLookupSymbolInImage(img, "", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
136 if (NSIsSymbolNameDefinedInImage(img, "__init")) {
137 NSSymbol* initsymbol;
138 void (*initfunc) (void);
139 initsymbol = NSLookupSymbolInImage(img, "__init", 0);
140 initfunc = NSAddressOfSymbol(initsymbol);
148 const char* dlerror()
150 static char* errbuf = NULL;
154 NSLinkEditError(&a, &b, &c, &d);
156 errbuf = (char*) malloc(256*sizeof(char));
160 snprintf(errbuf, 255, "%s in %s: %d %d", c, d, a, b);
162 } else if (last_was_error) {
164 snprintf(errbuf, 255, "Can't find symbol");
171 void* dlsym(void* handle, char* symbol)
173 if (handle == &dl_self) {
174 if (NSIsSymbolNameDefined(symbol)) {
176 retsym = NSLookupAndBindSymbol(symbol);
177 return NSAddressOfSymbol(retsym);
183 if (NSIsSymbolNameDefinedInImage(handle, symbol)) {
185 retsym = NSLookupSymbolInImage(handle, symbol, 0);
186 return NSAddressOfSymbol(retsym);
194 int dlclose(void *handle)
196 /* dlclose is not implemented, and never will be for dylibs.
197 * return -1 to signal an error; it's not used by SBCL anyhow */