📄 ltdl.c
字号:
* BIND_IMMEDIATE - Resolve symbol references when the library is loaded. * BIND_DEFERRED - Delay code symbol resolution until actual reference. * * Optionally: * BIND_FIRST - Place the library at the head of the symbol search * order. * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all * unsatisfied symbols as fatal. This flag allows * binding of unsatisfied code symbols to be deferred * until use. * [Perl: For certain libraries, like DCE, deferred * binding often causes run time problems. Adding * BIND_NONFATAL to BIND_IMMEDIATE still allows * unresolved references in situations like this.] * BIND_NOSTART - Do not call the initializer for the shared library * when the library is loaded, nor on a future call to * shl_unload(). * BIND_VERBOSE - Print verbose messages concerning possible * unsatisfied symbols. * * hp9000s700/hp9000s800: * BIND_RESTRICTED - Restrict symbols visible by the library to those * present at library load time. * DYNAMIC_PATH - Allow the loader to dynamically search for the * library specified by the path argument. */#ifndef DYNAMIC_PATH# define DYNAMIC_PATH 0#endif#ifndef BIND_RESTRICTED# define BIND_RESTRICTED 0#endif#define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)static lt_modulesys_shl_open (loader_data, filename) lt_user_data loader_data; const char *filename;{ static shl_t self = (shl_t) 0; lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L); /* Since searching for a symbol against a NULL module handle will also look in everything else that was already loaded and exported with the -E compiler flag, we always cache a handle saved before any modules are loaded. */ if (!self) { lt_ptr address; shl_findsym (&self, "main", TYPE_UNDEFINED, &address); } if (!filename) { module = self; } else { module = shl_load (filename, LT_BIND_FLAGS, 0L); if (!module) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); } } return module;}static intsys_shl_close (loader_data, module) lt_user_data loader_data; lt_module module;{ int errors = 0; if (module && (shl_unload ((shl_t) (module)) != 0)) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); ++errors; } return errors;}static lt_ptrsys_shl_sym (loader_data, module, symbol) lt_user_data loader_data; lt_module module; const char *symbol;{ lt_ptr address = 0; /* sys_shl_open should never return a NULL module handle */ if (module == (lt_module) 0) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); } else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address)) { if (!address) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); } } return address;}static struct lt_user_dlloader sys_shl = { 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0};#endif /* HAVE_SHL_LOAD *//* --- LOADLIBRARY() INTERFACE LOADER --- */#ifdef __WINDOWS__/* dynamic linking for Win32 */#include <windows.h>/* Forward declaration; required to implement handle search below. */static lt_dlhandle handles;static lt_modulesys_wll_open (loader_data, filename) lt_user_data loader_data; const char *filename;{ lt_dlhandle cur; lt_module module = 0; const char *errormsg = 0; char *searchname = 0; char *ext; char self_name_buf[MAX_PATH]; if (!filename) { /* Get the name of main module */ *self_name_buf = 0; GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf)); filename = ext = self_name_buf; } else { ext = strrchr (filename, '.'); } if (ext) { /* FILENAME already has an extension. */ searchname = lt_estrdup (filename); } else { /* Append a `.' to stop Windows from adding an implicit `.dll' extension. */ searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename)); if (searchname) sprintf (searchname, "%s.", filename); } if (!searchname) return 0;#if __CYGWIN__ { char wpath[MAX_PATH]; cygwin_conv_to_full_win32_path(searchname, wpath); module = LoadLibrary(wpath); }#else module = LoadLibrary (searchname);#endif LT_DLFREE (searchname); /* libltdl expects this function to fail if it is unable to physically load the library. Sadly, LoadLibrary will search the loaded libraries for a match and return one of them if the path search load fails. We check whether LoadLibrary is returning a handle to an already loaded module, and simulate failure if we find one. */ LT_DLMUTEX_LOCK (); cur = handles; while (cur) { if (!cur->module) { cur = 0; break; } if (cur->module == module) { break; } cur = cur->next; } LT_DLMUTEX_UNLOCK (); if (cur || !module) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); module = 0; } return module;}static intsys_wll_close (loader_data, module) lt_user_data loader_data; lt_module module;{ int errors = 0; if (FreeLibrary(module) == 0) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); ++errors; } return errors;}static lt_ptrsys_wll_sym (loader_data, module, symbol) lt_user_data loader_data; lt_module module; const char *symbol;{ lt_ptr address = GetProcAddress (module, symbol); if (!address) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); } return address;}static struct lt_user_dlloader sys_wll = { 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0};#endif /* __WINDOWS__ *//* --- LOAD_ADD_ON() INTERFACE LOADER --- */#ifdef __BEOS__/* dynamic linking for BeOS */#include <kernel/image.h>static lt_modulesys_bedl_open (loader_data, filename) lt_user_data loader_data; const char *filename;{ image_id image = 0; if (filename) { image = load_add_on (filename); } else { image_info info; int32 cookie = 0; if (get_next_image_info (0, &cookie, &info) == B_OK) image = load_add_on (info.name); } if (image <= 0) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); image = 0; } return (lt_module) image;}static intsys_bedl_close (loader_data, module) lt_user_data loader_data; lt_module module;{ int errors = 0; if (unload_add_on ((image_id) module) != B_OK) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); ++errors; } return errors;}static lt_ptrsys_bedl_sym (loader_data, module, symbol) lt_user_data loader_data; lt_module module; const char *symbol;{ lt_ptr address = 0; image_id image = (image_id) module; if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); address = 0; } return address;}static struct lt_user_dlloader sys_bedl = { 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0};#endif /* __BEOS__ *//* --- DLD_LINK() INTERFACE LOADER --- */#if HAVE_DLD/* dynamic linking with dld */#if HAVE_DLD_H#include <dld.h>#endifstatic lt_modulesys_dld_open (loader_data, filename) lt_user_data loader_data; const char *filename;{ lt_module module = strdup (filename); if (dld_link (filename) != 0) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); LT_DLFREE (module); module = 0; } return module;}static intsys_dld_close (loader_data, module) lt_user_data loader_data; lt_module module;{ int errors = 0; if (dld_unlink_by_file ((char*)(module), 1) != 0) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); ++errors; } else { LT_DLFREE (module); } return errors;}static lt_ptrsys_dld_sym (loader_data, module, symbol) lt_user_data loader_data; lt_module module; const char *symbol;{ lt_ptr address = dld_get_func (symbol); if (!address) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); } return address;}static struct lt_user_dlloader sys_dld = { 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0};#endif /* HAVE_DLD *//* --- DYLD() MACOSX/DARWIN INTERFACE LOADER --- */#if HAVE_DYLD#if HAVE_MACH_O_DYLD_H#if !defined(__APPLE_CC__) && !defined(__MWERKS__) && !defined(__private_extern__)/* Is this correct? Does it still function properly? */#define __private_extern__ extern#endif# include <mach-o/dyld.h>#endif#include <mach-o/getsect.h>/* We have to put some stuff here that isn't in older dyld.h files */#ifndef ENUM_DYLD_BOOL# define ENUM_DYLD_BOOL# undef FALSE# undef TRUE enum DYLD_BOOL { FALSE, TRUE };#endif#ifndef LC_REQ_DYLD# define LC_REQ_DYLD 0x80000000#endif#ifndef LC_LOAD_WEAK_DYLIB# define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)#endifstatic const struct mach_header * (*ltdl_NSAddImage)(const char *image_name, unsigned long options) = 0;static NSSymbol (*ltdl_NSLookupSymbolInImage)(const struct mach_header *image,const char *symbolName, unsigned long options) = 0;static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage)(const struct mach_header *image, const char *symbolName) = 0;static enum DYLD_BOOL (*ltdl_NSMakePrivateModulePublic)(NSModule module) = 0;#ifndef NSADDIMAGE_OPTION_NONE#define NSADDIMAGE_OPTION_NONE 0x0#endif#ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR#define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1#endif#ifndef NSADDIMAGE_OPTION_WITH_SEARCHING#define NSADDIMAGE_OPTION_WITH_SEARCHING 0x2#endif#ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED#define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4#endif#ifndef NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME#define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8#endif#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0#endif#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 0x1#endif#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY 0x2#endif#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR#define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4#endifstatic const char *lt_int_dyld_error(othererror) char* othererror;{/* return the dyld error string, or the passed in error string if none */ NSLinkEditErrors ler; int lerno; const char *errstr; const char *file; NSLinkEditError(&ler,&lerno,&file,&errstr); if (!errstr || !strlen(errstr)) errstr = othererror; return errstr;}static const struct mach_header *lt_int_dyld_get_mach_header_from_nsmodule(module) NSModule module;{/* There should probably be an apple dyld api for this */ int i=_dyld_image_count(); int j; const char *modname=NSNameOfModule(module); const struct mach_header *mh=NULL; if (!modname) return NULL; for (j = 0; j < i; j++) { if (!strcmp(_dyld_get_image_name(j),modname)) { mh=_dyld_get_image_header(j); break; } } return mh;}static const char* lt_int_dyld_lib_install_name(mh) const struct mach_header *mh;{/* NSAddImage is also used to get the loaded image, but it only works if the lib is installed, for uninstalled libs we need to check the install_names against each other. Note that this is still broken if DYLD_IMAGE_SUFFIX is set and a different lib was loaded as a result*/ int j; struct load_command *lc; unsigned long offset = sizeof(struct mach_header); const char* retStr=NULL; for (j = 0; j < mh->ncmds; j++) { lc = (struct load_command*)(((unsigned long)mh) + offset); if (LC_ID_DYLIB == lc->cmd) { retStr=(char*)(((struct dylib_command*)lc)->dylib.name.offset + (unsigned long)lc); } offset += lc->cmdsize; } return retStr;}static const struct mach_header *lt_int_dyld_match_loaded_lib_by_install_name(const char *name){ int i=_dyld_image_count(); int j; const struct mach_header *mh=NULL; const char *id=NULL; for (j = 0; j < i; j++) { id=lt_int_dyld_lib_install_name(_dyld_get_image_header(j)); if ((id) && (!strcmp(id,name))) { mh=_dyld_get_image_header(j); break; } } return mh;}static NSSymbollt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh) const char *symbol; const struct mach_header *mh;{ /* Safe to assume our mh is good */ int j; struct load_command *lc; unsigned long offset = sizeof(struct mach_header); NSSymbol retSym = 0; const struct mach_header *mh1; if ((ltdl_NSLookupSymbolInImage) && NSIsSymbolNameDefined(symbol) ) { for (j = 0; j < mh->ncmds; j++) { lc = (struct load_command*)(((unsigned long)mh) + offset); if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd)) { mh1=lt_int_dyld_match_loaded_lib_by_install_name((char*)(((struct dylib_command*)lc)->dylib.name.offset + (unsigned long)lc)); if (!mh1) { /* Maybe NSAddImage can find it */ mh1=ltdl_NSAddImage((char*)(((struct dylib_command*)lc)->dylib.name.offset + (unsigned long)lc), NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED + NSADDIMAGE_OPTION_WITH_SEARCHING + NSADDIMAGE_OPTION_RETURN_ON_ERROR ); } if (mh1) { retSym = ltdl_NSLookupSymbolInImage(mh1, symbol, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -