const char* dlerror() { NSLinkEditErrors c; int errorNumber; const char *fileName, *errorString; char *result = NULL; if (last_error) { NSLinkEditError(&c, &errorNumber, &fileName, &errorString); /* The errorString obtained by the above is too verbose for * our needs, so we just translate the errno. * * We also have simple fallbacks in case we've somehow lost * the context before this point. */ if (errorNumber) { result = strerror(errorNumber); } else if (DLSYM_ERROR == last_error) { result = "dlsym(3) failed"; } else if (DLOPEN_ERROR == last_error) { result = "dlopen(3) failed"; } last_error = 0; } return result; }
static NSModule pr_LoadMachDyldModule(const char *name) { NSObjectFileImage ofi; NSModule h = NULL; if (NSCreateObjectFileImageFromFile(name, &ofi) == NSObjectFileImageSuccess) { h = NSLinkModule(ofi, name, NSLINKMODULE_OPTION_PRIVATE | NSLINKMODULE_OPTION_RETURN_ON_ERROR); if (h == NULL) { NSLinkEditErrors linkEditError; int errorNum; const char *fileName; const char *errorString; NSLinkEditError(&linkEditError, &errorNum, &fileName, &errorString); PR_LOG(_pr_linker_lm, PR_LOG_MIN, ("LoadMachDyldModule error %d:%d for file %s:\n%s", linkEditError, errorNum, fileName, errorString)); } if (NSDestroyObjectFileImage(ofi) == FALSE) { if (h) { (void)NSUnLinkModule(h, NSUNLINKMODULE_OPTION_NONE); h = NULL; } } } return h; }
SharedLibraryRef dyldSharedLibraryLoader::loadSharedLibrary(const String& filename, const LoggerRef& logger) const { OW_LOG_DEBUG(logger, Format("Load request for %1 received.", filename)); NSObjectFileImage image = 0; NSObjectFileImageReturnCode dsoerr = NSCreateObjectFileImageFromFile(filename.c_str(), &image); const char* err_msg = NULL; NSModule libhandle = NULL; if (dsoerr == NSObjectFileImageSuccess) { libhandle = NSLinkModule(image, filename.c_str(), NSLINKMODULE_OPTION_RETURN_ON_ERROR | NSLINKMODULE_OPTION_PRIVATE); if (!libhandle) { NSLinkEditErrors errors; int errorNumber; const char *fileName; NSLinkEditError(&errors, &errorNumber, &fileName, &err_msg); } NSDestroyObjectFileImage(image); } else if ((dsoerr == NSObjectFileImageFormat || dsoerr == NSObjectFileImageInappropriateFile) && NSAddLibrary(filename.c_str()) == TRUE) { OW_LOG_ERROR(logger, Format("NSCreateObject: %1 failed with error \"%2\"", filename, dsoerr)); // libhandle = (NSModule)DYLD_LIBRARY_HANDLE; } else { err_msg = "cannot create object file image or add library"; OW_LOG_ERROR(logger, Format("NSCreateObject: %1 failed with error %2", filename, dsoerr)); } if (libhandle) { try { return SharedLibraryRef( new dyldSharedLibrary(libhandle, filename)); } catch (...) { NSUnLinkModule(libhandle, FALSE); throw; } } else { OW_LOG_ERROR(logger, Format("dyldSharedLibraryLoader::loadSharedLibrary:" " %1", err_msg)); return SharedLibraryRef( 0 ); } }
const char *vmddlerror( void ) { NSLinkEditErrors c; int errorNumber; const char *fileName; const char *errorString = NULL; NSLinkEditError(&c, &errorNumber, &fileName, &errorString); return errorString; }
static void pusherror (lua_State *L) { const char* err_str; const char* err_file; NSLinkEditErrors err; int err_num; NSLinkEditError(&err, &err_num, &err_file, &err_str); lua_pushstring(L, err_str); }
static void logDyldError (const char *action) { NSLinkEditErrors errors; int number; const char *file; const char *message; NSLinkEditError(&errors, &number, &file, &message); logMessage(LOG_ERR, "%.*s", (int)(strlen(message)-1), message); }
char * caml_dlerror(void) { NSLinkEditErrors c; int errnum; const char *fileName, *errorString; if (dlerror_string != NULL) return dlerror_string; NSLinkEditError(&c,&errnum,&fileName,&errorString); return (char *) errorString; }
static void *wx_darwin_dlopen(const char *path, int WXUNUSED(mode) /* mode is ignored */) { NSObjectFileImage ofile; NSModule handle = NULL; unsigned dyld_result = NSCreateObjectFileImageFromFile(path, &ofile); if ( dyld_result != NSObjectFileImageSuccess ) { handle = NULL; static const char *const errorStrings[] = { "%d: Object Image Load Failure", "%d: Object Image Load Success", "%d: Not an recognisable object file", "%d: No valid architecture", "%d: Object image has an invalid format", "%d: Invalid access (permissions?)", "%d: Unknown error code from NSCreateObjectFileImageFromFile" }; const int index = dyld_result < WXSIZEOF(errorStrings) ? dyld_result : WXSIZEOF(errorStrings) - 1; // this call to sprintf() is safe as strings above are fixed at // compile-time and are shorter than WXSIZEOF(dl_last_error) sprintf(dl_last_error, errorStrings[index], dyld_result); } else { handle = NSLinkModule ( ofile, path, NSLINKMODULE_OPTION_BINDNOW | NSLINKMODULE_OPTION_RETURN_ON_ERROR ); if ( !handle ) { NSLinkEditErrors err; int code; const char *filename; const char *errmsg; NSLinkEditError(&err, &code, &filename, &errmsg); strncpy(dl_last_error, errmsg, WXSIZEOF(dl_last_error)-1); dl_last_error[WXSIZEOF(dl_last_error)-1] = '\0'; } } return handle; }
static const char * dyld_dlerror() { NSLinkEditErrors ler; int lerno; const char *errstr; const char *file; NSLinkEditError(&ler, &lerno, &file, &errstr); if (!dyld_error_set) errstr=NULL; dyld_error_set=0; return errstr; }
CF_PRIVATE Boolean _CFBundleDYLDLoadFramework(CFBundleRef bundle, CFErrorRef *error) { // !!! Framework loading should be better. Can't unload frameworks. CFErrorRef localError = NULL, *subError = (error ? &localError : NULL); NSLinkEditErrors c = NSLinkEditUndefinedError; int errorNumber = 0; const char *fileName = NULL; const char *errorString = NULL; if (!bundle->_isLoaded) { CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); char buff[CFMaxPathSize]; if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) { void *image = (void *)NSAddImage(buff, NSADDIMAGE_OPTION_RETURN_ON_ERROR); #if LOG_BUNDLE_LOAD printf("dyld load framework %p, add image of %s returns image %p\n", bundle, buff, image); #endif /* LOG_BUNDLE_LOAD */ if (image) { bundle->_imageCookie = image; bundle->_isLoaded = true; } else { NSLinkEditError(&c, &errorNumber, &fileName, &errorString); if (error) { #if defined(BINARY_SUPPORT_DLFCN) _CFBundleDlfcnPreflight(bundle, subError); #endif /* BINARY_SUPPORT_DLFCN */ if (!localError) { CFStringRef tempString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString), debugString = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("error code %d, error number %d (%@)"), c, errorNumber, tempString); localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, debugString); if (tempString) CFRelease(tempString); if (debugString) CFRelease(debugString); } } else { CFStringRef tempString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString), executableString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, fileName); CFLog(__kCFLogBundle, CFSTR("Error loading %@: error code %d, error number %d (%@)"), executableString, c, errorNumber, tempString); if (tempString) CFRelease(tempString); if (executableString) CFRelease(executableString); } } } else { if (error) { localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError); } else { CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle); } } if (executableURL) CFRelease(executableURL); } if (!bundle->_isLoaded && error) *error = localError; return bundle->_isLoaded; }
/* Up to the caller to free() returned string */ static inline const char *dyld_error_str() { NSLinkEditErrors dylder; int dylderno; const char *dylderrstr; const char *dyldfile; const char* retStr = NULL; NSLinkEditError(&dylder, &dylderno, &dyldfile, &dylderrstr); if (dylderrstr && strlen(dylderrstr)) { retStr = malloc(strlen(dylderrstr) +1); strcpy((char*)retStr,dylderrstr); } return retStr; }
/* Return the dyld error string, or the passed in error string if none. */ static const char * dylderror (const char *errmsg) { NSLinkEditErrors ler; int lerno; const char *file; const char *errstr; NSLinkEditError (&ler, &lerno, &file, &errstr); if (! (errstr && *errstr)) { errstr = errmsg; } return errstr; }
nsresult XPCOMGlueLoad(const char *xpcomFile, GetFrozenFunctionsFunc *func) { const mach_header* lib = nsnull; if (xpcomFile[0] != '.' || xpcomFile[1] != '\0') { char xpcomDir[PATH_MAX]; if (realpath(xpcomFile, xpcomDir)) { char *lastSlash = strrchr(xpcomDir, '/'); if (lastSlash) { *lastSlash = '\0'; XPCOMGlueLoadDependentLibs(xpcomDir, ReadDependentCB); snprintf(lastSlash, PATH_MAX - strlen(xpcomDir), "/" XUL_DLL); sXULLibImage = NSAddImage(xpcomDir, NSADDIMAGE_OPTION_RETURN_ON_ERROR | NSADDIMAGE_OPTION_WITH_SEARCHING | NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME); } } lib = NSAddImage(xpcomFile, NSADDIMAGE_OPTION_RETURN_ON_ERROR | NSADDIMAGE_OPTION_WITH_SEARCHING | NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME); if (!lib) { NSLinkEditErrors linkEditError; int errorNum; const char *errorString; const char *fileName; NSLinkEditError(&linkEditError, &errorNum, &fileName, &errorString); fprintf(stderr, "XPCOMGlueLoad error %d:%d for file %s:\n%s\n", linkEditError, errorNum, fileName, errorString); } } *func = (GetFrozenFunctionsFunc) LookupSymbol(lib, "_NS_GetFrozenFunctions"); return *func ? NS_OK : NS_ERROR_NOT_AVAILABLE; }
char * pg_dlerror(void) { NSLinkEditErrors c; int errorNumber; const char *fileName; const char *errorString = NULL; switch (cofiff_result) { case NSObjectFileImageSuccess: /* must have failed in NSLinkModule */ NSLinkEditError(&c, &errorNumber, &fileName, &errorString); if (errorString == NULL || *errorString == '\0') errorString = "unknown link-edit failure"; break; case NSObjectFileImageFailure: errorString = "failed to open object file"; break; case NSObjectFileImageInappropriateFile: errorString = "inappropriate object file"; break; case NSObjectFileImageArch: errorString = "object file is for wrong architecture"; break; case NSObjectFileImageFormat: errorString = "object file has wrong format"; break; case NSObjectFileImageAccess: errorString = "insufficient permissions for object file"; break; default: errorString = "unknown failure to open object file"; break; } return (char *) errorString; }
/* Set and get the error string for use by dlerror */ static const char *error(int setget, const char *str, ...) { static char errstr[ERR_STR_LEN]; static int err_filled = 0; const 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); str_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); fprintf(stderr,"dyld: %s\n",dylderrstr); if (dylderrstr && str_len(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; }
MODULE_SCOPE int TclpLoadMemory( Tcl_Interp *interp, /* Used for error reporting. */ void *buffer, /* Buffer containing the desired code * (allocated with TclpLoadMemoryGetBuffer). */ int size, /* Allocation size of buffer. */ int codeSize, /* Size of code data read into buffer or -1 if * an error occurred and the buffer should * just be freed. */ Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded * file which will be passed back to * (*unloadProcPtr)() to unload the file. */ Tcl_FSUnloadFileProc **unloadProcPtr) /* Filled with address of Tcl_FSUnloadFileProc * function which should be used for this * file. */ { Tcl_DyldLoadHandle *dyldLoadHandle; NSObjectFileImage dyldObjFileImage = NULL; Tcl_DyldModuleHandle *modulePtr; NSModule module; const char *objFileImageErrMsg = NULL; /* * Try to create an object file image that we can load from. */ if (codeSize >= 0) { NSObjectFileImageReturnCode err = NSObjectFileImageSuccess; const struct fat_header *fh = buffer; uint32_t ms = 0; #ifndef __LP64__ const struct mach_header *mh = NULL; #define mh_size sizeof(struct mach_header) #define mh_magic MH_MAGIC #define arch_abi 0 #else const struct mach_header_64 *mh = NULL; #define mh_size sizeof(struct mach_header_64) #define mh_magic MH_MAGIC_64 #define arch_abi CPU_ARCH_ABI64 #endif if ((size_t) codeSize >= sizeof(struct fat_header) && fh->magic == OSSwapHostToBigInt32(FAT_MAGIC)) { uint32_t fh_nfat_arch = OSSwapBigToHostInt32(fh->nfat_arch); /* * Fat binary, try to find mach_header for our architecture */ TclLoadDbgMsg("Fat binary, %d archs", fh_nfat_arch); if ((size_t) codeSize >= sizeof(struct fat_header) + fh_nfat_arch * sizeof(struct fat_arch)) { void *fatarchs = (char*)buffer + sizeof(struct fat_header); const NXArchInfo *arch = NXGetLocalArchInfo(); struct fat_arch *fa; if (fh->magic != FAT_MAGIC) { swap_fat_arch(fatarchs, fh_nfat_arch, arch->byteorder); } fa = NXFindBestFatArch(arch->cputype | arch_abi, arch->cpusubtype, fatarchs, fh_nfat_arch); if (fa) { TclLoadDbgMsg("NXFindBestFatArch() successful: " "local cputype %d subtype %d, " "fat cputype %d subtype %d", arch->cputype | arch_abi, arch->cpusubtype, fa->cputype, fa->cpusubtype); mh = (void*)((char*)buffer + fa->offset); ms = fa->size; } else { TclLoadDbgMsg("NXFindBestFatArch() failed"); err = NSObjectFileImageInappropriateFile; } if (fh->magic != FAT_MAGIC) { swap_fat_arch(fatarchs, fh_nfat_arch, arch->byteorder); } } else { TclLoadDbgMsg("Fat binary header failure"); err = NSObjectFileImageInappropriateFile; } } else { /* * Thin binary */ TclLoadDbgMsg("Thin binary"); mh = buffer; ms = codeSize; } if (ms && !(ms >= mh_size && mh->magic == mh_magic && mh->filetype == MH_BUNDLE)) { TclLoadDbgMsg("Inappropriate file: magic %x filetype %d", mh->magic, mh->filetype); err = NSObjectFileImageInappropriateFile; } if (err == NSObjectFileImageSuccess) { err = NSCreateObjectFileImageFromMemory(buffer, codeSize, &dyldObjFileImage); if (err == NSObjectFileImageSuccess) { TclLoadDbgMsg("NSCreateObjectFileImageFromMemory() " "successful"); } else { objFileImageErrMsg = DyldOFIErrorMsg(err); TclLoadDbgMsg("NSCreateObjectFileImageFromMemory() failed: %s", objFileImageErrMsg); } } else { objFileImageErrMsg = DyldOFIErrorMsg(err); } } /* * If it went wrong (or we were asked to just deallocate), get rid of the * memory block and create an error message. */ if (dyldObjFileImage == NULL) { vm_deallocate(mach_task_self(), (vm_address_t) buffer, size); if (objFileImageErrMsg != NULL) { Tcl_AppendResult(interp, "NSCreateObjectFileImageFromMemory() " "error: ", objFileImageErrMsg, NULL); } return TCL_ERROR; } /* * Extract the module we want from the image of the object file. */ module = NSLinkModule(dyldObjFileImage, "[Memory Based Bundle]", NSLINKMODULE_OPTION_BINDNOW | NSLINKMODULE_OPTION_RETURN_ON_ERROR); NSDestroyObjectFileImage(dyldObjFileImage); if (module) { TclLoadDbgMsg("NSLinkModule() successful"); } else { NSLinkEditErrors editError; int errorNumber; const char *errorName, *errMsg; NSLinkEditError(&editError, &errorNumber, &errorName, &errMsg); TclLoadDbgMsg("NSLinkModule() failed: %s", errMsg); Tcl_AppendResult(interp, errMsg, NULL); return TCL_ERROR; } /* * Stash the module reference within the load handle we create and return. */ modulePtr = (Tcl_DyldModuleHandle *) ckalloc(sizeof(Tcl_DyldModuleHandle)); modulePtr->module = module; modulePtr->nextPtr = NULL; dyldLoadHandle = (Tcl_DyldLoadHandle *) ckalloc(sizeof(Tcl_DyldLoadHandle)); #if TCL_DYLD_USE_DLFCN dyldLoadHandle->dlHandle = NULL; #endif dyldLoadHandle->dyldLibHeader = NULL; dyldLoadHandle->modulePtr = modulePtr; *loadHandle = (Tcl_LoadHandle) dyldLoadHandle; *unloadProcPtr = &TclpUnloadFile; return TCL_OK; }
MODULE_SCOPE Tcl_PackageInitProc * TclpFindSymbol( Tcl_Interp *interp, /* For error reporting. */ Tcl_LoadHandle loadHandle, /* Handle from TclpDlopen. */ CONST char *symbol) /* Symbol name to look up. */ { Tcl_DyldLoadHandle *dyldLoadHandle = (Tcl_DyldLoadHandle *) loadHandle; Tcl_PackageInitProc *proc = NULL; const char *errMsg = NULL; Tcl_DString ds; const char *native; native = Tcl_UtfToExternalDString(NULL, symbol, -1, &ds); #if TCL_DYLD_USE_DLFCN if (dyldLoadHandle->dlHandle) { proc = dlsym(dyldLoadHandle->dlHandle, native); if (proc) { TclLoadDbgMsg("dlsym() successful"); } else { errMsg = dlerror(); TclLoadDbgMsg("dlsym() failed: %s", errMsg); } } else #endif /* TCL_DYLD_USE_DLFCN */ { #if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY) NSSymbol nsSymbol = NULL; Tcl_DString newName; /* * dyld adds an underscore to the beginning of symbol names. */ Tcl_DStringInit(&newName); Tcl_DStringAppend(&newName, "_", 1); native = Tcl_DStringAppend(&newName, native, -1); if (dyldLoadHandle->dyldLibHeader) { nsSymbol = NSLookupSymbolInImage(dyldLoadHandle->dyldLibHeader, native, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); if (nsSymbol) { TclLoadDbgMsg("NSLookupSymbolInImage() successful"); #ifdef DYLD_SUPPORTS_DYLIB_UNLOADING /* * Until dyld supports unloading of MY_DYLIB binaries, the * following is not needed. */ NSModule module = NSModuleForSymbol(nsSymbol); Tcl_DyldModuleHandle *modulePtr = dyldLoadHandle->modulePtr; while (modulePtr != NULL) { if (module == modulePtr->module) { break; } modulePtr = modulePtr->nextPtr; } if (modulePtr == NULL) { modulePtr = (Tcl_DyldModuleHandle *) ckalloc(sizeof(Tcl_DyldModuleHandle)); modulePtr->module = module; modulePtr->nextPtr = dyldLoadHandle->modulePtr; dyldLoadHandle->modulePtr = modulePtr; } #endif /* DYLD_SUPPORTS_DYLIB_UNLOADING */ } else { NSLinkEditErrors editError; int errorNumber; const char *errorName; NSLinkEditError(&editError, &errorNumber, &errorName, &errMsg); TclLoadDbgMsg("NSLookupSymbolInImage() failed: %s", errMsg); } } else if (dyldLoadHandle->modulePtr) { nsSymbol = NSLookupSymbolInModule( dyldLoadHandle->modulePtr->module, native); if (nsSymbol) { TclLoadDbgMsg("NSLookupSymbolInModule() successful"); } else { TclLoadDbgMsg("NSLookupSymbolInModule() failed"); } } if (nsSymbol) { proc = NSAddressOfSymbol(nsSymbol); if (proc) { TclLoadDbgMsg("NSAddressOfSymbol() successful"); } else { TclLoadDbgMsg("NSAddressOfSymbol() failed"); } } Tcl_DStringFree(&newName); #endif /* TCL_DYLD_USE_NSMODULE */ } Tcl_DStringFree(&ds); if (errMsg) { Tcl_AppendResult(interp, errMsg, NULL); } return proc; }
MODULE_SCOPE int TclpDlopen( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Obj *pathPtr, /* Name of the file containing the desired * code (UTF-8). */ Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded * file which will be passed back to * (*unloadProcPtr)() to unload the file. */ Tcl_FSUnloadFileProc **unloadProcPtr) /* Filled with address of Tcl_FSUnloadFileProc * function which should be used for this * file. */ { Tcl_DyldLoadHandle *dyldLoadHandle; #if TCL_DYLD_USE_DLFCN void *dlHandle = NULL; #endif #if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY) const struct mach_header *dyldLibHeader = NULL; Tcl_DyldModuleHandle *modulePtr = NULL; #endif #if TCL_DYLD_USE_NSMODULE NSLinkEditErrors editError; int errorNumber; const char *errorName, *objFileImageErrMsg = NULL; #endif const char *errMsg = NULL; int result; Tcl_DString ds; char *fileName = NULL; const char *nativePath, *nativeFileName = NULL; /* * First try the full path the user gave us. This is particularly * important if the cwd is inside a vfs, and we are trying to load using a * relative path. */ nativePath = Tcl_FSGetNativePath(pathPtr); #if TCL_DYLD_USE_DLFCN #if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 if (tclMacOSXDarwinRelease >= 8) #endif { dlHandle = dlopen(nativePath, RTLD_NOW | RTLD_LOCAL); if (!dlHandle) { /* * Let the OS loader examine the binary search path for whatever * string the user gave us which hopefully refers to a file on the * binary path. */ fileName = Tcl_GetString(pathPtr); nativeFileName = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds); dlHandle = dlopen(nativeFileName, RTLD_NOW | RTLD_LOCAL); } if (dlHandle) { TclLoadDbgMsg("dlopen() successful"); } else { errMsg = dlerror(); TclLoadDbgMsg("dlopen() failed: %s", errMsg); } } if (!dlHandle) #endif /* TCL_DYLD_USE_DLFCN */ { #if TCL_DYLD_USE_NSMODULE dyldLibHeader = NSAddImage(nativePath, NSADDIMAGE_OPTION_RETURN_ON_ERROR); if (dyldLibHeader) { TclLoadDbgMsg("NSAddImage() successful"); } else { NSLinkEditError(&editError, &errorNumber, &errorName, &errMsg); if (editError == NSLinkEditFileAccessError) { /* * The requested file was not found. Let the OS loader examine * the binary search path for whatever string the user gave us * which hopefully refers to a file on the binary path. */ if (!fileName) { fileName = Tcl_GetString(pathPtr); nativeFileName = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds); } dyldLibHeader = NSAddImage(nativeFileName, NSADDIMAGE_OPTION_WITH_SEARCHING | NSADDIMAGE_OPTION_RETURN_ON_ERROR); if (dyldLibHeader) { TclLoadDbgMsg("NSAddImage() successful"); } else { NSLinkEditError(&editError, &errorNumber, &errorName, &errMsg); TclLoadDbgMsg("NSAddImage() failed: %s", errMsg); } } else if ((editError == NSLinkEditFileFormatError && errorNumber == EBADMACHO) || editError == NSLinkEditOtherError){ NSObjectFileImageReturnCode err; NSObjectFileImage dyldObjFileImage; NSModule module; /* * The requested file was found but was not of type MH_DYLIB, * attempt to load it as a MH_BUNDLE. */ err = NSCreateObjectFileImageFromFile(nativePath, &dyldObjFileImage); if (err == NSObjectFileImageSuccess && dyldObjFileImage) { TclLoadDbgMsg("NSCreateObjectFileImageFromFile() " "successful"); module = NSLinkModule(dyldObjFileImage, nativePath, NSLINKMODULE_OPTION_BINDNOW | NSLINKMODULE_OPTION_RETURN_ON_ERROR); NSDestroyObjectFileImage(dyldObjFileImage); if (module) { modulePtr = (Tcl_DyldModuleHandle *) ckalloc(sizeof(Tcl_DyldModuleHandle)); modulePtr->module = module; modulePtr->nextPtr = NULL; TclLoadDbgMsg("NSLinkModule() successful"); } else { NSLinkEditError(&editError, &errorNumber, &errorName, &errMsg); TclLoadDbgMsg("NSLinkModule() failed: %s", errMsg); } } else { objFileImageErrMsg = DyldOFIErrorMsg(err); TclLoadDbgMsg("NSCreateObjectFileImageFromFile() failed: " "%s", objFileImageErrMsg); } } } #endif /* TCL_DYLD_USE_NSMODULE */ } if (0 #if TCL_DYLD_USE_DLFCN || dlHandle #endif #if TCL_DYLD_USE_NSMODULE || dyldLibHeader || modulePtr #endif ) { dyldLoadHandle = (Tcl_DyldLoadHandle *) ckalloc(sizeof(Tcl_DyldLoadHandle)); #if TCL_DYLD_USE_DLFCN dyldLoadHandle->dlHandle = dlHandle; #endif #if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY) dyldLoadHandle->dyldLibHeader = dyldLibHeader; dyldLoadHandle->modulePtr = modulePtr; #endif *loadHandle = (Tcl_LoadHandle) dyldLoadHandle; *unloadProcPtr = &TclpUnloadFile; result = TCL_OK; } else { Tcl_AppendResult(interp, errMsg, NULL); #if TCL_DYLD_USE_NSMODULE if (objFileImageErrMsg) { Tcl_AppendResult(interp, "\nNSCreateObjectFileImageFromFile() " "error: ", objFileImageErrMsg, NULL); } #endif result = TCL_ERROR; } if(fileName) { Tcl_DStringFree(&ds); } return result; }
bool CLibrary::Load(LPCTSTR lpLibFileName) { if(!Free()) return false; void *handler = 0; char name[MAX_PATHNAME_LEN+1]; #ifdef _UNICODE AString name2 = UnicodeStringToMultiByte(lpLibFileName); strcpy(name,nameWindowToUnix((const char *)name2)); #else strcpy(name,nameWindowToUnix(lpLibFileName)); #endif // replace ".dll" with ".so" size_t len = strlen(name); if ((len >=4) && (strcmp(name+len-4,".dll") == 0)) { strcpy(name+len-4,".so"); } #ifdef __ANDROID__ char tmp[MAX_PATHNAME_LEN+1]; if (strncmp(name, "./", 2) == 0) { strcpy(tmp, name+2); sprintf(name, "lib%s", tmp); } #endif TRACEN((printf("CLibrary::Load(this=%p,%ls) => %s\n",(void *)this,lpLibFileName,name))) #ifdef __APPLE_CC__ NSObjectFileImage image; NSObjectFileImageReturnCode nsret; nsret = NSCreateObjectFileImageFromFile (name, &image); if (nsret == NSObjectFileImageSuccess) { TRACEN((printf("NSCreateObjectFileImageFromFile(%s) : OK\n",name))) handler = (HMODULE)NSLinkModule(image,name,NSLINKMODULE_OPTION_RETURN_ON_ERROR | NSLINKMODULE_OPTION_PRIVATE | NSLINKMODULE_OPTION_BINDNOW); } else { TRACEN((printf("NSCreateObjectFileImageFromFile(%s) : ERROR\n",name))) } #elif ENV_BEOS // normalize path (remove things like "./", "..", etc..), otherwise it won't work BPath p(name, NULL, true); status_t err = B_OK; image_id image = load_add_on(p.Path()); TRACEN((printf("load_add_on(%s)=%d\n",p.Path(),(int)image))) if (image < 0) { err = (image_id)handler; handler = 0; } else { err = 0; handler = (HMODULE)image; } #else int options_dlopen = 0; #ifdef RTLD_LOCAL options_dlopen |= RTLD_LOCAL; #endif #ifdef RTLD_NOW options_dlopen |= RTLD_NOW; #endif #ifdef RTLD_GROUP #if ! (defined(hpux) || defined(__hpux)) options_dlopen |= RTLD_GROUP; // mainly for solaris but not for HPUX #endif #endif TRACEN((printf("CLibrary::Load - dlopen(%s,0x%d)\n",name,options_dlopen))) handler = dlopen(name,options_dlopen); #endif // __APPLE_CC__ TRACEN((printf("CLibrary::Load(%s) => %p\n",name,handler))) if (handler) { // Call DllMain() like in Windows : useless now // Propagate the value of global_use_utf16_conversion into the plugins int *tmp = (int *)local_GetProcAddress(handler,"global_use_utf16_conversion"); if (tmp) *tmp = global_use_utf16_conversion; #ifdef ENV_HAVE_LSTAT tmp = (int *)local_GetProcAddress(handler,"global_use_lstat"); if (tmp) *tmp = global_use_lstat; #endif // test construtors calls void (*fctTest)(void) = (void (*)(void))local_GetProcAddress(handler,"sync_TestConstructor"); if (fctTest) fctTest(); } else { #ifdef __APPLE_CC__ NSLinkEditErrors c; int num_err; const char *file,*err; NSLinkEditError(&c,&num_err,&file,&err); printf("Can't load '%ls' (%s)\n", lpLibFileName,err); #elif ENV_BEOS printf("Can't load '%ls' (%s)\n", lpLibFileName,strerror(err)); #else printf("Can't load '%ls' (%s)\n", lpLibFileName,dlerror()); #endif } _module = handler; TRACEN((printf("CLibrary::Load(this=%p,%ls) => _module=%p\n",(void *)this,lpLibFileName,_module))) return true; }
dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, const char *pathname, FILE *fp) { dl_funcptr p = NULL; char funcname[258]; NSObjectFileImageReturnCode rc; NSObjectFileImage image; NSModule newModule; NSSymbol theSym; const char *errString; char errBuf[512]; PyOS_snprintf(funcname, sizeof(funcname), "_init%.200s", shortname); #ifdef USE_DYLD_GLOBAL_NAMESPACE if (NSIsSymbolNameDefined(funcname)) { theSym = NSLookupAndBindSymbol(funcname); p = (dl_funcptr)NSAddressOfSymbol(theSym); return p; } #endif rc = NSCreateObjectFileImageFromFile(pathname, &image); switch(rc) { default: case NSObjectFileImageFailure: case NSObjectFileImageFormat: /* for these a message is printed on stderr by dyld */ errString = "Can't create object file image"; break; case NSObjectFileImageSuccess: errString = NULL; break; case NSObjectFileImageInappropriateFile: errString = "Inappropriate file type for dynamic loading"; break; case NSObjectFileImageArch: errString = "Wrong CPU type in object file"; break; case NSObjectFileImageAccess: errString = "Can't read object file (no access)"; break; } if (errString == NULL) { newModule = NSLinkModule(image, pathname, LINKOPTIONS); if (newModule == NULL) { int errNo; const char *fileName, *moreErrorStr; NSLinkEditErrors c; NSLinkEditError( &c, &errNo, &fileName, &moreErrorStr ); PyOS_snprintf(errBuf, 512, "Failure linking new module: %s: %s", fileName, moreErrorStr); errString = errBuf; } } if (errString != NULL) { PyErr_SetString(PyExc_ImportError, errString); return NULL; } #ifdef USE_DYLD_GLOBAL_NAMESPACE if (!NSIsSymbolNameDefined(funcname)) { /* UnlinkModule() isn't implemented in current versions, but calling it does no harm */ NSUnLinkModule(newModule, FALSE); PyErr_Format(PyExc_ImportError, "Loaded module does not contain symbol %.200s", funcname); return NULL; } theSym = NSLookupAndBindSymbol(funcname); #else theSym = NSLookupSymbolInModule(newModule, funcname); if ( theSym == NULL ) { NSUnLinkModule(newModule, FALSE); PyErr_Format(PyExc_ImportError, "Loaded module does not contain symbol %.200s", funcname); return NULL; } #endif p = (dl_funcptr)NSAddressOfSymbol(theSym); return p; }
APR_DECLARE(apr_status_t) apr_dso_load(apr_dso_handle_t **res_handle, const char *path, apr_pool_t *pool) { #if defined(DSO_USE_SHL) shl_t os_handle = shl_load(path, BIND_IMMEDIATE, 0L); #elif defined(DSO_USE_DYLD) NSObjectFileImage image; NSModule os_handle = NULL; NSObjectFileImageReturnCode dsoerr; const char* err_msg = NULL; dsoerr = NSCreateObjectFileImageFromFile(path, &image); if (dsoerr == NSObjectFileImageSuccess) { #if defined(NSLINKMODULE_OPTION_RETURN_ON_ERROR) && defined(NSLINKMODULE_OPTION_NONE) os_handle = NSLinkModule(image, path, NSLINKMODULE_OPTION_RETURN_ON_ERROR | NSLINKMODULE_OPTION_NONE); /* If something went wrong, get the errors... */ if (!os_handle) { NSLinkEditErrors errors; int errorNumber; const char *fileName; NSLinkEditError(&errors, &errorNumber, &fileName, &err_msg); } #else os_handle = NSLinkModule(image, path, FALSE); #endif NSDestroyObjectFileImage(image); } else if ((dsoerr == NSObjectFileImageFormat || dsoerr == NSObjectFileImageInappropriateFile) && NSAddLibrary(path) == TRUE) { os_handle = (NSModule)DYLD_LIBRARY_HANDLE; } else { err_msg = "cannot create object file image or add library"; } #elif defined(DSO_USE_DLFCN) #if defined(OSF1) || defined(SEQUENT) || defined(SNI) ||\ (defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)) void *os_handle = dlopen((char *)path, RTLD_NOW | RTLD_GLOBAL); #else int flags = RTLD_NOW | RTLD_GLOBAL; void *os_handle; #ifdef _AIX if (strchr(path + 1, '(') && path[strlen(path) - 1] == ')') { /* This special archive.a(dso.so) syntax is required for * the way libtool likes to build shared libraries on AIX. * dlopen() support for such a library requires that the * RTLD_MEMBER flag be enabled. */ flags |= RTLD_MEMBER; } #endif os_handle = dlopen(path, flags); #endif #endif /* DSO_USE_x */ *res_handle = apr_pcalloc(pool, sizeof(**res_handle)); if(os_handle == NULL) { #if defined(DSO_USE_SHL) (*res_handle)->errormsg = strerror(errno); return APR_EDSOOPEN; #elif defined(DSO_USE_DYLD) (*res_handle)->errormsg = (err_msg) ? err_msg : "link failed"; return APR_EDSOOPEN; #elif defined(DSO_USE_DLFCN) (*res_handle)->errormsg = dlerror(); return APR_EDSOOPEN; #endif } (*res_handle)->handle = (void*)os_handle; (*res_handle)->pool = pool; (*res_handle)->errormsg = NULL; apr_pool_cleanup_register(pool, *res_handle, dso_cleanup, apr_pool_cleanup_null); return APR_SUCCESS; }
CF_PRIVATE Boolean _CFBundleDYLDLoadBundle(CFBundleRef bundle, Boolean forceGlobal, CFErrorRef *error) { CFErrorRef localError = NULL, *subError = (error ? &localError : NULL); NSLinkEditErrors c = NSLinkEditUndefinedError; int errorNumber = 0; const char *fileName = NULL; const char *errorString = NULL; if (!bundle->_isLoaded) { CFURLRef executableURL = CFBundleCopyExecutableURL(bundle); char buff[CFMaxPathSize]; if (executableURL && CFURLGetFileSystemRepresentation(executableURL, true, (uint8_t *)buff, CFMaxPathSize)) { NSObjectFileImage image; NSObjectFileImageReturnCode retCode = NSCreateObjectFileImageFromFile(buff, &image); #if LOG_BUNDLE_LOAD printf("dyld load bundle %p, create image of %s returns image %p retcode %d\n", bundle, buff, image, retCode); #endif /* LOG_BUNDLE_LOAD */ if (retCode == NSObjectFileImageSuccess) { uint32_t options = forceGlobal ? NSLINKMODULE_OPTION_RETURN_ON_ERROR : (NSLINKMODULE_OPTION_BINDNOW | NSLINKMODULE_OPTION_PRIVATE | NSLINKMODULE_OPTION_RETURN_ON_ERROR); NSModule module = NSLinkModule(image, buff, options); #if LOG_BUNDLE_LOAD printf("dyld load bundle %p, link module of %s options 0x%x returns module %p image %p\n", bundle, buff, options, module, image); #endif /* LOG_BUNDLE_LOAD */ if (module) { bundle->_imageCookie = image; bundle->_moduleCookie = module; bundle->_isLoaded = true; } else { NSLinkEditError(&c, &errorNumber, &fileName, &errorString); if (error) { #if defined(BINARY_SUPPORT_DLFCN) _CFBundleDlfcnPreflight(bundle, subError); #endif /* BINARY_SUPPORT_DLFCN */ if (!localError) { CFStringRef tempString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString), debugString = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("error code %d, error number %d (%@)"), c, errorNumber, tempString); localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, debugString); if (tempString) CFRelease(tempString); if (debugString) CFRelease(debugString); } } else { CFStringRef tempString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, errorString), executableString = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, fileName); CFLog(__kCFLogBundle, CFSTR("Error loading %@: error code %d, error number %d (%@)"), executableString, c, errorNumber, tempString); if (tempString) CFRelease(tempString); if (executableString) CFRelease(executableString); } (void)NSDestroyObjectFileImage(image); } } else { if (error) { if (retCode == NSObjectFileImageArch) { localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableArchitectureMismatchError); } else if (retCode == NSObjectFileImageInappropriateFile) { Boolean hasRuntimeMismatch = false; uint32_t mainFlags = 0, bundleFlags = 0; if (_CFBundleGrokObjCImageInfoFromMainExecutable(NULL, &mainFlags) && (mainFlags & 0x2) != 0) { if (_CFBundleGetObjCImageInfo(bundle, NULL, &bundleFlags) && (bundleFlags & 0x2) == 0) hasRuntimeMismatch = true; } if (hasRuntimeMismatch) { localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableRuntimeMismatchError); } else { localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotLoadableError); } } else { #if defined(BINARY_SUPPORT_DLFCN) _CFBundleDlfcnPreflight(bundle, subError); #endif /* BINARY_SUPPORT_DLFCN */ if (!localError) { CFStringRef debugString = CFStringCreateWithFormat(kCFAllocatorSystemDefault, NULL, CFSTR("dyld returns %d"), retCode); localError = _CFBundleCreateErrorDebug(CFGetAllocator(bundle), bundle, CFBundleExecutableLinkError, debugString); CFRelease(debugString); } } } else { CFLog(__kCFLogBundle, CFSTR("dyld returns %d when trying to load %@"), retCode, executableURL); } } } else { if (error) { localError = _CFBundleCreateError(CFGetAllocator(bundle), bundle, CFBundleExecutableNotFoundError); } else { CFLog(__kCFLogBundle, CFSTR("Cannot find executable for bundle %@"), bundle); } } if (executableURL) CFRelease(executableURL); } if (!bundle->_isLoaded && error) *error = localError; return bundle->_isLoaded; }
cc_libhandle cc_dl_open(const char * filename) { cc_libhandle h = new struct cc_libhandle_struct; h->nativehnd = NULL; h->libname = NULL_STR; #ifdef HAVE_DL_LIB #ifdef HAVE_DYLD_RUNTIME_BINDING /* Mac OS X: Search for library shipped with bundled Inventor framework or directly in application bundle. */ if (h->nativehnd == NULL) { cc_string * path = cc_find_file(filename); if (cc_string_length(path) > 0) { if (cc_dl_debugging()) { cc_debugerror_postinfo("cc_dl_open", "opening: %s", cc_string_get_text(path)); } h->nativehnd = dlopen(cc_string_get_text(path), RTLD_LAZY); } cc_string_destruct(path); } #endif /* HAVE_DYLD_RUNTIME_BINDING */ if (h->nativehnd == NULL) { /* try loading path-less */ h->nativehnd = dlopen(filename, RTLD_LAZY); } /* If dlopen() fails for any reason than not being able to find the dynamic link-library given by "filename" on disk, we should really detect it and report an error, whether we're running in debug mode or release mode. The libdl interface doesn't provide any means to do that, though, so we'll just /assume/ that a NULL return means the library couldn't be found. But if a special debugging environment variable is found, we'll spit out the error message, which could prove useful for remote debugging: */ if (cc_dl_debugging() && (h->nativehnd == NULL)) { const char * e = dlerror(); if (e) { cc_debugerror_post("cc_dl_open", "dlopen(\"%s\") failed with: '%s'", filename, e); } } #elif defined (HAVE_DYLD_RUNTIME_BINDING) if (filename == NULL) { /* Simulate the behaviour of dlopen(NULL) by returning a handle to the first image loaded by the dynamic linker, which is the current process. See dyld(3). Note that this handle is not necessary for the dyld cc_dl_sym() implementation, but it makes it possible to use cc_dl_open() in the "classic" dlopen() style (where a NULL return value would indicate failure). */ h->nativehnd = _dyld_get_image_header(0); } else { /* Note that we must use NSAddImage, since we want to load a shared library, instead of NSCreateObjectFileImageFromFile() and NSLinkModule(), which work only with loadable modules/bundles. See NSModule(3), NSObjectFileImage(3) and http://fink.sourceforge.net/doc/porting/shared.php for details. */ cc_string * path = cc_find_file(filename); if (cc_string_length(path) > 0) { if (cc_dl_debugging()) { cc_debugerror_postinfo("cc_dlopen", "opening: %s", cc_string_get_text(path)); } h->nativehnd = (void *) NSAddImage(cc_string_get_text(path), NSADDIMAGE_OPTION_RETURN_ON_ERROR); if (cc_dl_debugging() && !h->nativehnd) { NSLinkEditErrors c; int e; const char * file; const char * errstr; NSLinkEditError(&c, &e, &file, &errstr); cc_debugerror_post("cc_dlopen", "%s", errstr); } cc_string_destruct(path); } } #elif defined (HAVE_WINDLL_RUNTIME_BINDING) /* We don't want to call LoadLibrary(NULL) because this causes a crash on some Windows platforms (Crashes on Windows2000 has been reported). 20021101 thammer. */ if (filename != NULL) { /* Don't use GetModuleHandle(): LoadLibrary() will *not* load a new image if the module is already loaded, it will only inc the reference count. Also, GetModuleHandle() doesn't inc the reference count, so it is dangerous in the sense that the module could be free'd from somewhere else between us opening it, and until it is used for resolving symbols. */ h->nativehnd = LoadLibrary(filename); if (cc_dl_debugging() && (h->nativehnd == NULL)) { cc_string funcstr; cc_string_construct(&funcstr); cc_string_sprintf(&funcstr, "LoadLibrary(\"%s\")", filename ? filename : "(null)"); cc_win32_print_error("cc_dl_open", cc_string_get_text(&funcstr), GetLastError()); cc_string_clean(&funcstr); } } else { h->nativehnd = GetModuleHandle(NULL); if (cc_dl_debugging() && (h->nativehnd == NULL)) { cc_win32_print_error("cc_dl_open", "GetModuleHandle(NULL)", GetLastError()); } } #elif defined (HAVE_DLD_LIB) /* FIXME: there is a good reason to try to use shn_load() *first*, then dlopen() on HP-UX: according to a discussion on the libtool mailinglist, dlopen() for HP-UX was buggy in an official release, needing a patch to function properly. This would take some changes to the configure checks (we cut off further checking if libdl is found), and any code that depends on _either_ HAVE_DL_LIB _or_ HAVE_DLD_LIB being defined, but not both at the same time. 20010626 mortene. */ /* This define not available on older versions. */ #ifndef DYNAMIC_PATH #define DYNAMIC_PATH 0 #endif /* DYNAMIC_PATH */ /* Handle attempt to look at running executable image and already loaded dynamic libraries. */ if (filename == NULL) { shl_t exehnd = (shl_t)0; void * dummy; int ret = shl_findsym(&exehnd, "main", TYPE_UNDEFINED, &dummy); if (ret != -1) { h->nativehnd = exehnd; } else { const char * e = strerror(errno); cc_debugerror_post("cc_dl_open", "shl_findsym(&NULL, \"main\", ...) failed with: '%s'", e); } } else { h->nativehnd = shl_load(filename, BIND_IMMEDIATE|BIND_NONFATAL|DYNAMIC_PATH, 0L); /* If a special debugging environment variable is found, we'll spit out the error message, which could prove useful for remote debugging. Note that if shl_load() fails for any reason than not being able to find the dynamic link-library given by "filename" on disk, we detect it and report an error, whether we're running in debug mode or release mode. ENOENT means "the specified library does not exist" -- all other errors should be warned about no matter what. */ if ((h->nativehnd == NULL) && (cc_dl_debugging() || (errno != ENOENT))) { const char * e = strerror(errno); cc_debugerror_post("cc_dl_open", "shl_load(\"%s\") failed with: '%s'", filename ? filename : "(null)", e); } } #endif if (h->nativehnd == NULL) { delete h; h = NULL; } else { h->libname = filename ? filename : NULL_STR; if (cc_dl_debugging()) { #ifdef HAVE_WINDLL_RUNTIME_BINDING char libpath[512]; DWORD retval = GetModuleFileName((HINSTANCE) h->nativehnd, libpath, sizeof(libpath)); assert(retval > 0 && "GetModuleFileName() failed"); libpath[sizeof(libpath) - 1] = 0; cc_debugerror_postinfo("cc_dl_open", "Opened library '%s'", libpath); #elif defined (HAVE_DL_LIB) || defined (HAVE_DLD_LIB) cc_debugerror_postinfo("cc_dl_open", "Opening library '%s'", h->libname.getString()); #endif } } if (cc_dl_debugging() && h) { cc_debugerror_postinfo("cc_dl_open", "\"%s\" success => cc_libhandle==%p, nativehnd==%p", h->libname.getString(), h, h->nativehnd); } return h; }
void * cc_dl_sym(cc_libhandle handle, const char * symbolname) { void * ptr = NULL; #ifdef HAVE_DL_LIB if ((handle == NULL) || (handle->nativehnd == NULL)) return NULL; ptr = dlsym((void *)handle->nativehnd, symbolname); if (cc_dl_debugging()) { const char * e = dlerror(); if (e) { cc_debugerror_post("cc_dl_sym", "dlsym(\"%s\", \"%s\") failed with: '%s'", handle->libname.getString(), symbolname, e); } } #elif defined (HAVE_DYLD_RUNTIME_BINDING) /* Note: The dlopen() version returns NULL here if handle or handle->nativehnd are NULL, but we do not need a handle for symbol lookup on Mac OS X - if we have one, it makes the lookup faster, but that's all, so we can get away with having no valid handle. */ NSSymbol symbol = NULL; char * mangledname; NSLinkEditErrors c; int e; const char * file; const char * errstr; if (cc_dl_debugging()) { cc_debugerror_postinfo("cc_dl_sym", "Looking up symbol %s", symbolname); } mangledname = malloc(strlen(symbolname) + 2); strcpy(mangledname + 1, symbolname); mangledname[0] = '_'; if (handle && handle->nativehnd) { if (NSIsSymbolNameDefinedInImage(handle->nativehnd, mangledname)) symbol = NSLookupSymbolInImage(handle->nativehnd, mangledname, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); } /* If we did not specifically load the library ourselves (handle->nativehnd being NULL), or if the symbol could not be found in the library, let's try if we can find it in any of the loaded libs. */ if (!symbol && NSIsSymbolNameDefined(mangledname)) { symbol = NSLookupAndBindSymbol(mangledname); } if (cc_dl_debugging()) { if (symbol == NULL) { NSLinkEditError(&c, &e, &file, &errstr); cc_debugerror_post("cc_dl_sym", "symbol %s not found: %s", symbolname, errstr); } } free (mangledname); ptr = symbol ? NSAddressOfSymbol(symbol) : NULL; #elif defined (HAVE_WINDLL_RUNTIME_BINDING) if ((handle == NULL) || (handle->nativehnd == NULL)) return NULL; ptr = dl_internal::cstyle_cast<void *>(GetProcAddress((HINSTANCE) handle->nativehnd, symbolname)); if (cc_dl_debugging() && (ptr == NULL)) { cc_string funcstr; cc_string_construct(&funcstr); cc_string_sprintf(&funcstr, "GetProcAddress(\"%s\", \"%s\")", handle->libname.getString(), symbolname); cc_win32_print_error("cc_dl_sym", cc_string_get_text(&funcstr), GetLastError()); cc_string_clean(&funcstr); } #elif defined (HAVE_DLD_LIB) { int retval = shl_findsym((shl_t *)(&handle->nativehnd), symbolname, TYPE_UNDEFINED, &ptr); if (cc_dl_debugging() && (retval == -1)) { const char * e = strerror(errno); cc_debugerror_post("cc_dl_sym", "shl_findsym(\"%s\", \"%s\", ...) failed with: '%s'", handle->libname.getString(), symbolname, e); } } #endif return ptr; }
static struct dlstatus * loadModule(const char * path, const struct stat * sbuf, int mode) { NSObjectFileImage ofi = 0; NSObjectFileImageReturnCode ofirc; struct dlstatus * dls; NSLinkEditErrors ler; int lerno; const char* errstr; const char* file; void (*init)(void); ofirc = NSCreateObjectFileImageFromFile(path, &ofi); switch (ofirc) { case NSObjectFileImageSuccess: break; case NSObjectFileImageInappropriateFile: if (isFlagSet(mode, RTLD_LOCAL)) { warning("trying to open a .dylib with RTLD_LOCAL"); error("unable to open this file with RTLD_LOCAL"); return NULL; } break; case NSObjectFileImageFailure: error("object file setup failure"); return NULL; case NSObjectFileImageArch: error("no object for this architecture"); return NULL; case NSObjectFileImageFormat: error("bad object file format"); return NULL; case NSObjectFileImageAccess: error("can't read object file"); return NULL; default: error("unknown error from NSCreateObjectFileImageFromFile()"); return NULL; } dls = lookupStatus(sbuf); if (!dls) { dls = allocStatus(); } if (!dls) { error("unable to allocate memory"); return NULL; } dls->lib=0; if (ofirc == NSObjectFileImageInappropriateFile) { if ((dls->lib = NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR))) { debug("Dynamic lib loaded at %ld",dls->lib); ofi = MAGIC_DYLIB_OFI; dls->module = MAGIC_DYLIB_MOD; ofirc = NSObjectFileImageSuccess; } } else { /* Should change this to take care of RLTD_LAZY etc */ dls->module = NSLinkModule(ofi, path, NSLINKMODULE_OPTION_RETURN_ON_ERROR | NSLINKMODULE_OPTION_PRIVATE | NSLINKMODULE_OPTION_BINDNOW); NSDestroyObjectFileImage(ofi); } if (!dls->module) { NSLinkEditError(&ler,&lerno,&file,&errstr); free(dls); error(errstr); return NULL; } insertStatus(dls, sbuf); if ((init = dlsymIntern(dls, "__init",0))) { debug("calling _init()"); init(); } return dls; }
static struct dlstatus *loadModule(const char *path, const struct stat *sbuf, int mode) { NSObjectFileImage ofi = 0; NSObjectFileImageReturnCode ofirc; struct dlstatus *dls; NSLinkEditErrors ler; int lerno; const char *errstr; const char *file; void (*init) (void); ofirc = NSCreateObjectFileImageFromFile(path, &ofi); switch (ofirc) { case NSObjectFileImageSuccess: break; case NSObjectFileImageInappropriateFile: if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage) { if (isFlagSet(mode, RTLD_LOCAL)) { warning("trying to open a .dylib with RTLD_LOCAL"); error("unable to open this file with RTLD_LOCAL"); return NULL; } } else { error("opening this file is unsupported on this system"); return NULL; } break; case NSObjectFileImageFailure: error("object file setup failure"); return NULL; case NSObjectFileImageArch: error("no object for this architecture"); return NULL; case NSObjectFileImageFormat: error("bad object file format"); return NULL; case NSObjectFileImageAccess: error("can't read object file"); return NULL; default: error("unknown error from NSCreateObjectFileImageFromFile()"); return NULL; } dls = lookupStatus(sbuf); if (!dls) { dls = allocStatus(); } if (!dls) { error("unable to allocate memory"); return NULL; } dls->lib = 0; if (ofirc == NSObjectFileImageInappropriateFile) { if ((dls->lib = dyld_NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR))) { debug("Dynamic lib loaded at %ld", dls->lib); ofi = MAGIC_DYLIB_OFI; dls->module = MAGIC_DYLIB_MOD; ofirc = NSObjectFileImageSuccess; /* Although it is possible with a bit of work to modify this so it works and functions with RTLD_NOW, I don't deem it necessary at the moment */ } if (!(dls->module)) { NSLinkEditError(&ler, &lerno, &file, &errstr); if (!errstr || (!strlen(errstr))) error("Can't open this file type"); else error(errstr); if ((dls->flags & DL_IN_LIST) == 0) { free(dls); } return NULL; } } else { dls->module = NSLinkModule(ofi, path, NSLINKMODULE_OPTION_RETURN_ON_ERROR | NSLINKMODULE_OPTION_PRIVATE | (isFlagSet(mode, RTLD_NOW) ? NSLINKMODULE_OPTION_BINDNOW : 0)); NSDestroyObjectFileImage(ofi); if (dls->module) { dls->lib = get_mach_header_from_NSModule(dls->module); } } if (!dls->module) { NSLinkEditError(&ler, &lerno, &file, &errstr); if ((dls->flags & DL_IN_LIST) == 0) { free(dls); } error(errstr); return NULL; } insertStatus(dls, sbuf); dls = reference(dls, mode); if ((init = dlsymIntern(dls, "__init", 0))) { debug("calling _init()"); init(); } return dls; }
/** * Load a dynamically linked library using a system dependent method. * * \param p_this vlc object * \param psz_file library file * \param p_handle the module handle returned * \return 0 on success as well as the module handle. */ int module_Load( vlc_object_t *p_this, const char *psz_file, module_handle_t *p_handle ) { module_handle_t handle; #if defined(HAVE_DL_DYLD) NSObjectFileImage image; NSObjectFileImageReturnCode ret; ret = NSCreateObjectFileImageFromFile( psz_file, &image ); if( ret != NSObjectFileImageSuccess ) { msg_Warn( p_this, "cannot create image from `%s'", psz_file ); return -1; } /* Open the dynamic module */ handle = NSLinkModule( image, psz_file, NSLINKMODULE_OPTION_RETURN_ON_ERROR ); if( !handle ) { NSLinkEditErrors errors; const char *psz_file, *psz_err; int i_errnum; NSLinkEditError( &errors, &i_errnum, &psz_file, &psz_err ); msg_Warn( p_this, "cannot link module `%s' (%s)", psz_file, psz_err ); NSDestroyObjectFileImage( image ); return -1; } /* Destroy our image, we won't need it */ NSDestroyObjectFileImage( image ); #elif defined(HAVE_DL_BEOS) handle = load_add_on( psz_file ); if( handle < 0 ) { msg_Warn( p_this, "cannot load module `%s'", psz_file ); return -1; } #elif defined(HAVE_DL_WINDOWS) wchar_t psz_wfile[MAX_PATH]; MultiByteToWideChar( CP_ACP, 0, psz_file, -1, psz_wfile, MAX_PATH ); #ifndef UNDER_CE /* FIXME: this is not thread-safe -- Courmisch */ UINT mode = SetErrorMode (SEM_FAILCRITICALERRORS); SetErrorMode (mode|SEM_FAILCRITICALERRORS); #endif handle = LoadLibraryW( psz_wfile ); #ifndef UNDER_CE SetErrorMode (mode); #endif if( handle == NULL ) { char *psz_err = GetWindowsError(); msg_Warn( p_this, "cannot load module `%s' (%s)", psz_file, psz_err ); free( psz_err ); return -1; } #elif defined(HAVE_DL_DLOPEN) # if defined (RTLD_NOW) const int flags = RTLD_NOW; # elif defined (DL_LAZY) const int flags = DL_LAZY; # else const int flags = 0; # endif handle = dlopen( psz_file, flags ); if( handle == NULL ) { msg_Warn( p_this, "cannot load module `%s' (%s)", psz_file, dlerror() ); return -1; } #elif defined(HAVE_DL_SHL_LOAD) handle = shl_load( psz_file, BIND_IMMEDIATE | BIND_NONFATAL, NULL ); if( handle == NULL ) { msg_Warn( p_this, "cannot load module `%s' (%m)", psz_file ); return -1; } #else # error "Something is wrong in modules.c" #endif *p_handle = handle; return 0; }
int main() { // NSCreateObjectFileImageFromMemory is only available on Mac OS X - not iPhone OS #if __MAC_OS_X_VERSION_MIN_REQUIRED NSObjectFileImage ofi; if ( NSCreateObjectFileImageFromFile("test.bundle", &ofi) != NSObjectFileImageSuccess ) { FAIL("NSCreateObjectFileImageFromFile failed"); return 0; } NSModule mod = NSLinkModule(ofi, "test.bundle", NSLINKMODULE_OPTION_NONE); if ( mod == NULL ) { FAIL("NSLinkModule failed"); return 0; } NSSymbol sym = NSLookupSymbolInModule(mod, "_setValue"); if ( sym == NULL ) { FAIL("NSLookupSymbolInModule failed"); return 0; } setter func = NSAddressOfSymbol(sym); (*func)(1); //fprintf(stderr, "address of foo() = %p in bundle first load %p\n", func, mod); NSModule mod2 = NSLinkModule(ofi, "test2.bundle", NSLINKMODULE_OPTION_NONE); if ( mod2 == NULL ) { NSLinkEditErrors c; int errorNumber; const char* fileName; const char* errorString; NSLinkEditError(&c, &errorNumber, &fileName, &errorString); FAIL("2nd NSLinkModule failed: %s", errorString); return 0; } if ( mod == mod2 ) { FAIL("2nd NSLinkModule return same function address as first"); return 0; } NSSymbol sym2getter = NSLookupSymbolInModule(mod2, "_getValue"); if ( sym2getter == NULL ) { FAIL("2nd NSLookupSymbolInModule failed"); return 0; } getter func2getter = NSAddressOfSymbol(sym2getter); if ( (*func2getter)() != 0 ) { FAIL("_getValue() on second link returned non-zero"); return 0; } NSSymbol sym2 = NSLookupSymbolInModule(mod2, "_setValue"); if ( sym2 == NULL ) { FAIL("2nd NSLookupSymbolInModule failed"); return 0; } setter func2 = NSAddressOfSymbol(sym2); (*func2)(2); //fprintf(stderr, "address of foo() = %p in bundle second load %p\n", func2, mod2); if ( func == func2 ) { FAIL("2nd NSAddressOfSymbol return same function address as 1st"); return 0; } NSModule mod3 = NSLinkModule(ofi, "test3.bundle", NSLINKMODULE_OPTION_NONE); if ( mod3 == NULL ) { FAIL("3rd NSLinkModule failed"); return 0; } if ( mod3 == mod ) { FAIL("3rd NSLinkModule return same function address as 1st"); return 0; } if ( mod3 == mod2 ) { FAIL("3rd NSLinkModule return same function address as 2nd"); return 0; } NSSymbol sym3 = NSLookupSymbolInModule(mod3, "_setValue"); if ( sym3 == NULL ) { FAIL("3rd NSLookupSymbolInModule failed"); return 0; } setter func3 = NSAddressOfSymbol(sym3); (*func3)(3); //fprintf(stderr, "address of foo() = %p in bundle third load %p\n", func3, mod3); if ( func3 == func ) { FAIL("3rd NSAddressOfSymbol return same function address as 1st"); return 0; } if ( func3 == func2 ) { FAIL("3rd NSAddressOfSymbol return same function address as 2nd"); return 0; } if ( !NSUnLinkModule(mod, NSUNLINKMODULE_OPTION_NONE) ) { FAIL("NSUnLinkModule failed"); return 0; } if ( !NSUnLinkModule(mod3, NSUNLINKMODULE_OPTION_NONE) ) { FAIL("3rd NSUnLinkModule failed"); return 0; } if ( !NSUnLinkModule(mod2, NSUNLINKMODULE_OPTION_NONE) ) { FAIL("2nd NSUnLinkModule failed"); return 0; } // now link again after unlinking everything NSModule mod4 = NSLinkModule(ofi, "test4.bundle", NSLINKMODULE_OPTION_NONE); if ( mod4 == NULL ) { FAIL("4th NSLinkModule failed"); return 0; } // check that this is really a new copy by verifying the getValue() returns zero NSSymbol sym4getter = NSLookupSymbolInModule(mod4, "_getValue"); if ( sym4getter == NULL ) { FAIL("4th NSLookupSymbolInModule failed"); return 0; } getter func4getter = NSAddressOfSymbol(sym4getter); if ( (*func4getter)() != 0 ) { FAIL("_getValue() on fourth link returned non-zero"); return 0; } if ( !NSUnLinkModule(mod4, NSUNLINKMODULE_OPTION_NONE) ) { FAIL("4th NSUnLinkModule failed"); return 0; } if ( !NSDestroyObjectFileImage(ofi) ) { FAIL("NSDestroyObjectFileImage failed"); return 0; } #endif PASS("bundle-multi-link"); return 0; }
/* dlopen */ void *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; /* 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); if(!module) { NSLinkEditErrors dylder; int dylderno; const char * dyldfile; const char * dylderstr; NSLinkEditError(&dylder, &dylderno, &dyldfile, &dylderstr); error(0, dylderstr); return 0; } /* 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: 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 void * dlsymIntern(struct dlstatus * dls, const char *symbol,int canSetError) { NSSymbol * nssym = 0; /* If it is a module - use NSLookupSymbolInModule */ if (dls->module != MAGIC_DYLIB_MOD) { nssym = NSLookupSymbolInModule(dls->module, symbol); if (!nssym && canSetError) error("unable to find symbol \"%s\"", symbol); } else { if (dls->lib != NULL) { /* dylib, use NSIsSymbolNameDefinedInImage */ if (NSIsSymbolNameDefinedInImage(dls->lib,symbol)) { nssym = NSLookupSymbolInImage(dls->lib, symbol, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR ); } } else { /* Global context, use NSLookupAndBindSymbol */ if (NSIsSymbolNameDefined(symbol)) { /* There doesn't seem to be a return on error option for this call??? this is potentially broken, if binding fails, it will improperly exit the application. If anyone comes up with an example of this happening I will install error handlers before making this call, and remove them afterwards. The error handlers themselves can cause problems as they are global to the process, and errors that have nothing to do with dlcompat could cause the error handlers to get called */ nssym = NSLookupAndBindSymbol(symbol); } } if (!nssym) { NSLinkEditErrors ler; int lerno; const char* errstr; const char* file; NSLinkEditError(&ler,&lerno,&file,&errstr); if (errstr && strlen(errstr)) { if (canSetError) error(errstr); debug("%s",errstr); } else if (canSetError) { error("unable to find symbol \"%s\"", symbol); } } } if (!nssym) return NULL; return NSAddressOfSymbol(nssym); }