From a6ed4d2d86725c85bb906a4569ebdcfbb0712f4c Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Sun, 7 Dec 2003 19:20:10 +0000 Subject: - Solution for fixing plugins, which now runs without -ldl at OSX 10.2/3 Code from Peter O'Gorman * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ @@ -102,7 +104,203 @@ void PIL_dynlib_close(PILdynlib *lib) { free(lib); } -#else /* Unix & MacOS X */ +#else +#ifdef __APPLE__ /* MacOS X */ + +#include +#include +#include + +#define ERR_STR_LEN 256 + +struct PILdynlib { + void *handle; +}; + +char *osxerror(int setget, const char *str, ...) +{ + static char errstr[ERR_STR_LEN]; + static int err_filled = 0; + char *retval; + NSLinkEditErrors ler; + int lerno; + const char *dylderrstr; + const char *file; + va_list arg; + if (setget <= 0) + { + va_start(arg, str); + strncpy(errstr, "dlsimple: ", ERR_STR_LEN); + vsnprintf(errstr + 10, ERR_STR_LEN - 10, str, arg); + va_end(arg); + /* We prefer to use the dyld error string if setget is 0 */ + if (setget == 0) { + NSLinkEditError(&ler, &lerno, &file, &dylderrstr); + printf("dyld: %s\n",dylderrstr); + if (dylderrstr && strlen(dylderrstr)) + strncpy(errstr,dylderrstr,ERR_STR_LEN); + } + err_filled = 1; + retval = NULL; + } + else + { + if (!err_filled) + retval = NULL; + else + retval = errstr; + err_filled = 0; + } + return retval; +} + +void *osxdlopen(const char *path, int mode) +{ + void *module = 0; + NSObjectFileImage ofi = 0; + NSObjectFileImageReturnCode ofirc; + static int (*make_private_module_public) (NSModule module) = 0; + unsigned int flags = NSLINKMODULE_OPTION_RETURN_ON_ERROR | NSLINKMODULE_OPTION_PRIVATE; + + /* If we got no path, the app wants the global namespace, use -1 as the marker + in this case */ + if (!path) + return (void *)-1; + + /* Create the object file image, works for things linked with the -bundle arg to ld */ + ofirc = NSCreateObjectFileImageFromFile(path, &ofi); + switch (ofirc) + { + case NSObjectFileImageSuccess: + /* It was okay, so use NSLinkModule to link in the image */ + if (!(mode & RTLD_LAZY)) flags += NSLINKMODULE_OPTION_BINDNOW; + module = NSLinkModule(ofi, path,flags); + /* Don't forget to destroy the object file image, unless you like leaks */ + NSDestroyObjectFileImage(ofi); + /* If the mode was global, then change the module, this avoids + multiply defined symbol errors to first load private then make + global. Silly, isn't it. */ + if ((mode & RTLD_GLOBAL)) + { + if (!make_private_module_public) + { + _dyld_func_lookup("__dyld_NSMakePrivateModulePublic", + (unsigned long *)&make_private_module_public); + } + make_private_module_public(module); + } + break; + case NSObjectFileImageInappropriateFile: + /* It may have been a dynamic library rather than a bundle, try to load it */ + module = (void *)NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR); + break; + case NSObjectFileImageFailure: + osxerror(0,"Object file setup failure : \"%s\"", path); + return 0; + case NSObjectFileImageArch: + osxerror(0,"No object for this architecture : \"%s\"", path); + return 0; + case NSObjectFileImageFormat: + osxerror(0,"Bad object file format : \"%s\"", path); + return 0; + case NSObjectFileImageAccess: + osxerror(0,"Can't read object file : \"%s\"", path); + return 0; + } + if (!module) + osxerror(0, "Can not open \"%s\"", path); + return module; +} + +PILdynlib *PIL_dynlib_open(char *name) { + void *handle= osxdlopen(name, RTLD_LAZY); + + if (handle) { + PILdynlib *lib= malloc(sizeof(*lib)); + lib->handle= handle; + + return lib; + } else { + return NULL; + } +} + +void *PIL_dynlib_find_symbol(PILdynlib* lib, char *symname) +{ + int sym_len = strlen(symname); + void *value = NULL; + char *malloc_sym = NULL; + NSSymbol *nssym = 0; + malloc_sym = malloc(sym_len + 2); + if (malloc_sym) + { + sprintf(malloc_sym, "_%s", symname); + /* If the lib->handle is -1, if is the app global context */ + if (lib->handle == (void *)-1) + { + /* Global context, use NSLookupAndBindSymbol */ + if (NSIsSymbolNameDefined(malloc_sym)) + { + nssym = NSLookupAndBindSymbol(malloc_sym); + } + } + /* Now see if the lib->handle is a struch mach_header* or not, use NSLookupSymbol in image + for libraries, and NSLookupSymbolInModule for bundles */ + else + { + /* Check for both possible magic numbers depending on x86/ppc byte order */ + if ((((struct mach_header *)lib->handle)->magic == MH_MAGIC) || + (((struct mach_header *)lib->handle)->magic == MH_CIGAM)) + { + if (NSIsSymbolNameDefinedInImage((struct mach_header *)lib->handle, malloc_sym)) + { + nssym = NSLookupSymbolInImage((struct mach_header *)lib->handle, + malloc_sym, + NSLOOKUPSYMBOLINIMAGE_OPTION_BIND + | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); + } + + } + else + { + nssym = NSLookupSymbolInModule(lib->handle, malloc_sym); + } + } + if (!nssym) + { + osxerror(0, "symname \"%s\" Not found", symname); + } + value = NSAddressOfSymbol(nssym); + free(malloc_sym); + } + else + { + osxerror(-1, "Unable to allocate memory"); + } + return value; +} + +char *PIL_dynlib_get_error_as_string(PILdynlib* lib) +{ + return osxerror(1, (char *)NULL); +} + +void PIL_dynlib_close(PILdynlib *lib) +{ + if ((((struct mach_header *)lib->handle)->magic == MH_MAGIC) || + (((struct mach_header *)lib->handle)->magic == MH_CIGAM)) + { + osxerror(-1, "Can't remove dynamic libraries on darwin"); + } + if (!NSUnLinkModule(lib->handle, 0)) + { + osxerror(0, "unable to unlink module %s", NSNameOfModule(lib->handle)); + } + + free(lib); +} + +#else /* Unix */ #include @@ -138,3 +336,4 @@ void PIL_dynlib_close(PILdynlib *lib) { } #endif +#endif -- cgit v1.2.3