1.0.22.22: (SETF FIND-CLASSOID) to drop DEFTYPE lambda-lists and source-locations
[sbcl/tcr.git] / src / runtime / ppc-darwin-dlshim.c
blobdbf82bf8b0a28f033840bea5587b5e26affd8a56
1 /*
2 * These functions emulate a small subset of the dlopen / dlsym
3 * functionality under Darwin's Mach-O dyld system.
4 */
6 /*
7 * This software is part of the SBCL system. See the README file for
8 * more information.
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>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.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;
37 #define DLSYM_ERROR 1
38 #define DLOPEN_ERROR 2
40 static int last_error = 0;
42 void
43 dlshim_image_callback(struct mach_header* ptr, unsigned long phooey)
45 callback_count++;
46 last_header = ptr;
49 int
50 lib_path_count(void)
52 char* libpath;
53 int i;
54 int count;
55 libpath = getenv("DYLD_LIBRARY_PATH");
56 count = 1;
57 if (libpath) {
58 for (i = 0; libpath[i] != '\0'; i++) {
59 if (libpath[i] == ':') count++;
62 return count;
65 const char*
66 lib_path_prefixify(int index, const char* filename)
68 static char* retbuf = NULL;
69 int fi, li, i, count;
70 char* libpath;
71 if (!retbuf) {
72 retbuf = (char*) malloc(1024*sizeof(char));
74 count = 0;
75 fi = 0;
76 li = -1;
77 libpath = getenv("DYLD_LIBRARY_PATH");
78 if (libpath) {
79 i = 0;
80 while (count != index && libpath[i] != '\0') {
81 if (libpath[i] == ':') count++;
82 i++;
84 fi = i;
85 while (libpath[i] != '\0' && libpath[i] != ':') {
86 i++;
88 li = i - 1;
90 if (li - fi > 0) {
91 if (li - fi + 1 > 1022 - strlen(filename)) {
92 retbuf =
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);
98 return retbuf;
99 } else {
100 return filename;
104 const void*
105 dlopen(const char* filename, int flags)
107 static char has_callback = 0;
108 if (!has_callback) {
109 _dyld_register_func_for_add_image(dlshim_image_callback);
111 if (!filename) {
112 return &dl_self;
113 } else {
114 const struct mach_header* img = NULL;
115 if (!img)
116 img = NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
117 if (!img)
118 img = NSAddImage(filename,
119 NSADDIMAGE_OPTION_RETURN_ON_ERROR |
120 NSADDIMAGE_OPTION_WITH_SEARCHING);
121 if (!img) {
122 NSObjectFileImage fileImage;
123 callback_count = 0;
124 last_header = NULL;
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)
132 img = last_header;
135 if (!img) {
136 NSObjectFileImage fileImage;
137 int i, maxi;
138 const char* prefixfilename;
139 maxi = lib_path_count();
140 for (i = 0; i < maxi && !img; i++) {
141 prefixfilename = lib_path_prefixify(i, filename);
142 callback_count = 0;
143 last_header = NULL;
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)
151 img = last_header;
155 if (img) {
156 if (flags & RTLD_NOW) {
157 NSLookupSymbolInImage(img, "",
158 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY |
159 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
161 if (NSIsSymbolNameDefinedInImage(img, "__init")) {
162 NSSymbol* initsymbol;
163 void (*initfunc) (void);
164 initsymbol = NSLookupSymbolInImage(img, "__init", 0);
165 initfunc = NSAddressOfSymbol(initsymbol);
166 initfunc();
168 } else
169 last_error = DLOPEN_ERROR;
170 return img;
174 const char*
175 dlerror()
177 NSLinkEditErrors c;
178 int errorNumber;
179 const char *fileName, *errorString;
180 char *result = NULL;
182 if (last_error) {
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. */
189 if (errorNumber) {
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";
196 last_error = 0;
199 return result;
202 void*
203 dlsym(void* handle, char* symbol)
205 if (handle == &dl_self) {
206 if (NSIsSymbolNameDefined(symbol)) {
207 NSSymbol* retsym;
208 retsym = NSLookupAndBindSymbol(symbol);
209 return NSAddressOfSymbol(retsym);
210 } else {
211 last_error = DLSYM_ERROR;
212 return NULL;
214 } else {
215 if (NSIsSymbolNameDefinedInImage(handle, symbol)) {
216 NSSymbol* retsym;
217 retsym = NSLookupSymbolInImage(handle, symbol, 0);
218 return NSAddressOfSymbol(retsym);
219 } else {
220 last_error = DLSYM_ERROR;
221 return NULL;
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 */
231 return -1;