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
;
38 #define DLOPEN_ERROR 2
40 static int last_error
= 0;
43 dlshim_image_callback(struct mach_header
* ptr
, unsigned long 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")) {
162 NSSymbol
* initsymbol
;
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 */