/* A function called through the vtable to initialise this loader. */ static int vl_init (lt_user_data loader_data) { int errors = 0; if (! dyld_cannot_close) { if (!_dyld_present ()) { ++errors; } else { (void) _dyld_func_lookup ("__dyld_NSAddImage", (unsigned long*) <__addimage); (void) _dyld_func_lookup ("__dyld_NSLookupSymbolInImage", (unsigned long*)<__image_symbol); (void) _dyld_func_lookup ("__dyld_NSIsSymbolNameDefinedInImage", (unsigned long*) <__image_symbol_p); (void) _dyld_func_lookup ("__dyld_NSMakePrivateModulePublic", (unsigned long*) <__module_export); dyld_cannot_close = lt_dladderror ("can't close a dylib"); } } return errors; }
static void dlcompat_init_func(void) { _dyld_func_lookup("__dyld_NSAddImage", (unsigned long *)&dyld_NSAddImage); _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage", (unsigned long *)&dyld_NSIsSymbolNameDefinedInImage); _dyld_func_lookup("__dyld_NSLookupSymbolInImage", (unsigned long *)&dyld_NSLookupSymbolInImage); if (pthread_mutex_init(&dlcompat_mutex, NULL)) exit(1); if (pthread_key_create(&dlerror_key, &dlerrorfree)) exit(1); }
bool check_dyld_func_lookup() { void* address; // dlopen does not exist, something is wrong if ( ! _dyld_func_lookup("__dyld_dlopen", &address) ) return false; // if a garbage string returns true, something is wrong if ( _dyld_func_lookup("blablah", &address) ) return false; // looks good return true; }
/* dlopen */ void *darwin_dlopen(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; sys::coreout << "darwin try bind module: " << path << sys::eofl; /* 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); sys::coreout << "darwin bind module: " << path << sys::eofl; /* 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); sys::coreout << " wrong filetype use addimage: " << (void*)module << sys::eofl; break; case NSObjectFileImageFailure: error(0,"Object file setup failure : \"%s\"", path); return 0; case NSObjectFileImageArch: error(0,"No object for this architecture : \"%s\"", path); return 0; case NSObjectFileImageFormat: error(0,"Bad object file format : \"%s\"", path); return 0; case NSObjectFileImageAccess: error(0,"Can't read object file : \"%s\"", path); return 0; } if (!module) error(0, "Can not open \"%s\"", path); return module; }
static int promoteLocalToGlobal(struct dlstatus *dls) { static int (*p) (NSModule module) = 0; debug("promoting"); if (!p) _dyld_func_lookup("__dyld_NSMakePrivateModulePublic", (unsigned long *)&p); return (dls->module == MAGIC_DYLIB_MOD) || (p && p(dls->module)); }
/* We're running on 10.3.9. Find the address of the system atexit() function. So easy to say, so hard to do. */ static atexit_p find_atexit_10_3 (void) { unsigned int (*dyld_image_count_fn)(void); const char *(*dyld_get_image_name_fn)(unsigned int image_index); const void *(*dyld_get_image_header_fn)(unsigned int image_index); const void *(*NSLookupSymbolInImage_fn)(const void *image, const char *symbolName, unsigned int options); void *(*NSAddressOfSymbol_fn)(const void *symbol); unsigned i, count; /* Find some dyld functions. */ _dyld_func_lookup("__dyld_image_count", &dyld_image_count_fn); _dyld_func_lookup("__dyld_get_image_name", &dyld_get_image_name_fn); _dyld_func_lookup("__dyld_get_image_header", &dyld_get_image_header_fn); _dyld_func_lookup("__dyld_NSLookupSymbolInImage", &NSLookupSymbolInImage_fn); _dyld_func_lookup("__dyld_NSAddressOfSymbol", &NSAddressOfSymbol_fn); /* If any of these don't exist, that's an error. */ if (! dyld_image_count_fn || ! dyld_get_image_name_fn || ! dyld_get_image_header_fn || ! NSLookupSymbolInImage_fn || ! NSAddressOfSymbol_fn) return NULL; count = dyld_image_count_fn (); for (i = 0; i < count; i++) { const char * path = dyld_get_image_name_fn (i); const void * image; const void * symbol; if (strcmp (path, "/usr/lib/libSystem.B.dylib") != 0) continue; image = dyld_get_image_header_fn (i); if (! image) return NULL; /* '4' is NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR. */ symbol = NSLookupSymbolInImage_fn (image, "_atexit", 4); if (! symbol) return NULL; return NSAddressOfSymbol_fn (symbol); } return NULL; }
enum bool _dyld_bind_fully_image_containing_address( unsigned long *address) { static enum bool (*p)(unsigned long *) = NULL; if(p == NULL) _dyld_func_lookup("__dyld_bind_fully_image_containing_address", (unsigned long *)&p); return(p(address)); }
void _dyld_lookup_and_bind( const char *symbol_name, unsigned long *address, void **module) { static void (*p)(const char *, unsigned long *, void **) = NULL; if(p == NULL) _dyld_func_lookup("__dyld_lookup_and_bind", (unsigned long *)&p); p(symbol_name, address, module); }
void _dyld_lookup_and_bind_with_hint( const char *symbol_name, const char *library_name_hint, unsigned long *address, void **module) { static void (*p)(const char *, const char *, unsigned long *, void **) = NULL; if(p == NULL) _dyld_func_lookup("__dyld_lookup_and_bind_with_hint", (unsigned long *)&p); p(symbol_name, library_name_hint, address, module); }
void NSLinkEditError( NSLinkEditErrors *c, int *errorNumber, const char **fileName, const char **errorString) { static void (*p)(NSLinkEditErrors *c, int *errorNumber, const char **fileName, const char **errorString) = NULL; if(p == NULL) _dyld_func_lookup("__dyld_link_edit_error", (unsigned long *)&p); if(p != NULL) p(c, errorNumber, fileName, errorString); }
NSModule NSLinkModule( NSObjectFileImage objectFileImage, const char *moduleName, unsigned long options) { static NSModule (*p)(char *object_addr, unsigned long object_size, const char *moduleName, unsigned long options) = NULL; struct ofi *ofi; ofi = (struct ofi *)objectFileImage; if(p == NULL) _dyld_func_lookup("__dyld_link_module", (unsigned long *)&p); return(p(ofi->ofile.object_addr, ofi->ofile.object_size, moduleName, options)); }
/* * NSMakePrivateModulePublic() is not part of the public dyld API so we define * it here. The internal dyld function pointer for * __dyld_NSMakePrivateModulePublic is returned so thats all that maters to get * the functionality need to implement the dlopen() interfaces. */ static enum DYLD_BOOL NSMakePrivateModulePublic( NSModule module) { static enum DYLD_BOOL (*p)(NSModule module) = NULL; if(p == NULL) _dyld_func_lookup("__dyld_NSMakePrivateModulePublic", (unsigned long *)&p); if(p == NULL) { #ifdef DARWIN_LOADER_DEBUG printf("_dyld_func_lookup of __dyld_NSMakePrivateModulePublic " "failed\n"); #endif return(FALSE); } return(p(module)); }
enum bool NSUnLinkModule( NSModule module, unsigned long options) { static enum bool (*p)(NSModule module, unsigned long options) = NULL; if(p == NULL) { _dyld_func_lookup("__dyld_unlink_module", (unsigned long *)&p); } if(p != NULL) { /* printf("_dyld_func_lookup of __dyld_unlink_module worked\n"); */ return(p(module, options)); } else{ /* printf("_dyld_func_lookup of __dyld_unlink_module failed\n"); */ return(FALSE); } }