⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dlfcn.c

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*Copyright (c) 2002 Jorge Acereda  <jacereda@users.sourceforge.net> &                   Peter O'Gorman <ogorman@users.sourceforge.net>                   Portions may be copyright others, see the AUTHORS file included with thisdistribution.                  Maintained by Peter O'Gorman <ogorman@users.sourceforge.net>Bug Reports and other queries should go to <ogorman@users.sourceforge.net>Permission is hereby granted, free of charge, to any person obtaininga copy of this software and associated documentation files (the"Software"), to deal in the Software without restriction, includingwithout limitation the rights to use, copy, modify, merge, publish,distribute, sublicense, and/or sell copies of the Software, and topermit persons to whom the Software is furnished to do so, subject tothe following conditions:The above copyright notice and this permission notice shall beincluded in all copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OFMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE ANDNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BELIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTIONOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTIONWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.*/#include <pthread.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <stdarg.h>#include <limits.h>#include <mach-o/dyld.h>#include <mach-o/nlist.h>#include <mach-o/getsect.h>/* Just playing to see if it would compile with the freebsd headers, it does, * but because of the different values for RTLD_LOCAL etc, it would break binary * compat... oh well */#ifndef __BSD_VISIBLE#define __BSD_VISIBLE 1#endif#include "dlfcn.h"/* This is not available on 10.1 */#ifndef LC_LOAD_WEAK_DYLIB#define	LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)#endif/* With this stuff here, this thing may actually compile/run on 10.0 systems * Not that I have a 10.0 system to test it on anylonger */#ifndef LC_REQ_DYLD#define LC_REQ_DYLD 0x80000000#endif#ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED#define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4#endif#ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR#define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1#endif#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0#endif#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR#define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4#endif/* These symbols will be looked for in dyld */static const struct mach_header *(*dyld_NSAddImage) (const char *, unsigned long) = 0;static int (*dyld_NSIsSymbolNameDefinedInImage) (const struct mach_header *, const char *) = 0;static NSSymbol(*dyld_NSLookupSymbolInImage)	(const struct mach_header *, const char *, unsigned long) = 0;/* Define this to make dlcompat reuse data block. This way in theory we save * a little bit of overhead. However we then couldn't correctly catch excess * calls to dlclose(). Hence we don't use this feature */#undef REUSE_STATUS/* Size of the internal error message buffer (used by dlerror()) */#define ERR_STR_LEN			251/* Maximum number of search paths supported by getSearchPath */#define MAX_SEARCH_PATHS	32#define MAGIC_DYLIB_OFI ((NSObjectFileImage) 'DYOF')#define MAGIC_DYLIB_MOD ((NSModule) 'DYMO')/* internal flags */#define DL_IN_LIST 0x01/* our mutex */static pthread_mutex_t dlcompat_mutex;/* Our thread specific storage */static pthread_key_t dlerror_key;struct dlthread{	int lockcnt;	unsigned char errset;	char errstr[ERR_STR_LEN];};/* This is our central data structure. Whenever a module is loaded via * dlopen(), we create such a struct. */struct dlstatus{	struct dlstatus *next;		/* pointer to next element in the linked list */	NSModule module;	const struct mach_header *lib;	int refs;					/* reference count */	int mode;					/* mode in which this module was loaded */	dev_t device;	ino_t inode;	int flags;					/* Any internal flags we may need */};/* Head node of the dlstatus list */static struct dlstatus mainStatus = { 0, MAGIC_DYLIB_MOD, NULL, -1, RTLD_GLOBAL, 0, 0, 0 };static struct dlstatus *stqueue = &mainStatus;/* Storage for the last error message (used by dlerror()) *//* static char err_str[ERR_STR_LEN]; *//* static int err_filled = 0; *//* Prototypes to internal functions */static void debug(const char *fmt, ...);static void error(const char *str, ...);static const char *safegetenv(const char *s);static const char *searchList(void);static const char *getSearchPath(int i);static const char *getFullPath(int i, const char *file);static const struct stat *findFile(const char *file, const char **fullPath);static int isValidStatus(struct dlstatus *status);static inline int isFlagSet(int mode, int flag);static struct dlstatus *lookupStatus(const struct stat *sbuf);static void insertStatus(struct dlstatus *dls, const struct stat *sbuf);static int promoteLocalToGlobal(struct dlstatus *dls);static void *reference(struct dlstatus *dls, int mode);static void *dlsymIntern(struct dlstatus *dls, const char *symbol, int canSetError);static struct dlstatus *allocStatus(void);static struct dlstatus *loadModule(const char *path, const struct stat *sbuf, int mode);static NSSymbol *search_linked_libs(const struct mach_header *mh, const char *symbol);static const char *get_lib_name(const struct mach_header *mh);static const struct mach_header *get_mach_header_from_NSModule(NSModule * mod);static void dlcompat_init_func(void);static inline void dlcompat_init_check(void);static inline void dolock(void);static inline void dounlock(void);static void dlerrorfree(void *data);static void resetdlerror(void);static const struct mach_header *my_find_image(const char *name);static const struct mach_header *image_for_address(const void *address);static inline const char *dyld_error_str(void);#if FINK_BUILD/* Two Global Functions */void *dlsym_prepend_underscore(void *handle, const char *symbol);void *dlsym_auto_underscore(void *handle, const char *symbol);/* And their _intern counterparts */static void *dlsym_prepend_underscore_intern(void *handle, const char *symbol);static void *dlsym_auto_underscore_intern(void *handle, const char *symbol);#endif/* Functions */static void debug(const char *fmt, ...){#if DEBUG > 1	va_list arg;	va_start(arg, fmt);	fprintf(stderr, "DLDEBUG: ");	vfprintf(stderr, fmt, arg);	fprintf(stderr, "\n");	fflush(stderr);	va_end(arg);#else	(void)fmt;#endif}static void error(const char *str, ...){	va_list arg;	struct dlthread  *tss;	char * err_str;	va_start(arg, str);	tss = pthread_getspecific(dlerror_key);	err_str = tss->errstr;	strncpy(err_str, "dlcompat: ", ERR_STR_LEN);	vsnprintf(err_str + 10, ERR_STR_LEN - 10, str, arg);	va_end(arg);	debug("ERROR: %s\n", err_str);	tss->errset = 1;}static void warning(const char *str){#if DEBUG > 0	fprintf(stderr, "WARNING: dlcompat: %s\n", str);#else	(void)str;#endif}static const char *safegetenv(const char *s){	const char *ss = getenv(s);	return ss ? ss : "";}/* because this is only used for debugging and error reporting functions, we * don't really care about how elegant it is... it could use the load * commands to find the install name of the library, but... */static const char *get_lib_name(const struct mach_header *mh){	unsigned long count = _dyld_image_count();	unsigned long i;	const char *val = NULL;	if (mh)	{		for (i = 0; i < count; i++)		{			if (mh == _dyld_get_image_header(i))			{				val = _dyld_get_image_name(i);				break;			}		}	}	return val;}/* Returns the mach_header for the module bu going through all the loaded images * and finding the one with the same name as the module. There really ought to be * an api for doing this, would be faster, but there isn't one right now */static const struct mach_header *get_mach_header_from_NSModule(NSModule * mod){	const char *mod_name = NSNameOfModule(mod);	struct mach_header *mh = NULL;	unsigned long count = _dyld_image_count();	unsigned long i;	debug("Module name: %s", mod_name);	for (i = 0; i < count; i++)	{		if (!strcmp(mod_name, _dyld_get_image_name(i)))		{			mh = _dyld_get_image_header(i);			break;		}	}	return mh;}/* Compute and return a list of all directories that we should search when * trying to locate a module. We first look at the values of LD_LIBRARY_PATH * and DYLD_LIBRARY_PATH, and then finally fall back to looking into * /usr/lib and /lib. Since both of the environments variables can contain a * list of colon seperated paths, we simply concat them and the two other paths * into one big string, which we then can easily parse. * Splitting this string into the actual path list is done by getSearchPath() */static const char *searchList(){	size_t buf_size;	static char *buf=NULL;	const char *ldlp = safegetenv("LD_LIBRARY_PATH");	const char *dyldlp = safegetenv("DYLD_LIBRARY_PATH");	const char *stdpath = getenv("DYLD_FALLBACK_LIBRARY_PATH");	if (!stdpath)		stdpath = "/usr/local/lib:/lib:/usr/lib";	if (!buf)	{			buf_size = strlen(ldlp) + strlen(dyldlp) + strlen(stdpath) + 4;		buf = malloc(buf_size);		snprintf(buf, buf_size, "%s%s%s%s%s%c", dyldlp, (dyldlp[0] ? ":" : ""), ldlp, (ldlp[0] ? ":" : ""),				 stdpath, '\0');	}	return buf;}/* Returns the ith search path from the list as computed by searchList() */static const char *getSearchPath(int i){	static const char *list = 0;	static char **path = (char **)0;	static int end = 0;	static int numsize = MAX_SEARCH_PATHS;	static char **tmp;	/* So we can call free() in the "destructor" we use i=-1 to return the alloc'd array */	if (i == -1)	{		return (const char*)path;	}	if (!path)	{		path = (char **)calloc(MAX_SEARCH_PATHS, sizeof(char **));	}	if (!list && !end)		list = searchList();	if (i >= (numsize))	{		debug("Increasing size for long PATH");		tmp = (char **)calloc((MAX_SEARCH_PATHS + numsize), sizeof(char **));		if (tmp)		{			memcpy(tmp, path, sizeof(char **) * numsize);			free(path);			path = tmp;			numsize += MAX_SEARCH_PATHS;		}		else		{			return 0;		}	}	while (!path[i] && !end)	{		path[i] = strsep((char **)&list, ":");		if (path[i][0] == 0)			path[i] = 0;		end = (list == 0);	}	return path[i];}static const char *getFullPath(int i, const char *file){	static char buf[PATH_MAX];	const char *path = getSearchPath(i);	if (path)	{		snprintf(buf, PATH_MAX, "%s/%s", path, file);	}	return path ? buf : 0;}/* Given a file name, try to determine the full path for that file. Starts * its search in the current directory, and then tries all paths in the  * search list in the order they are specified there. */static const struct stat *findFile(const char *file, const char **fullPath){	int i = 0;	static struct stat sbuf;	char *fileName;	debug("finding file %s", file);	*fullPath = file;	if (0 == stat(file, &sbuf))		return &sbuf;	if (strchr(file, '/'))		return 0;				/* If the path had a / we don't look in env var places */	fileName = NULL;	if (!fileName)		fileName = (char *)file;	while ((*fullPath = getFullPath(i++, fileName)))	{		if (0 == stat(*fullPath, &sbuf))			return &sbuf;	}	;	return 0;}/* Determine whether a given dlstatus is valid or not */static int isValidStatus(struct dlstatus *status){	/* Walk the list to verify status is contained in it */	struct dlstatus *dls = stqueue;	while (dls && status != dls)		dls = dls->next;	if (dls == 0)		error("invalid handle");	else if ((dls->module == 0) || (dls->refs == 0))		error("handle to closed library");	else		return TRUE;	return FALSE;}static inline int isFlagSet(int mode, int flag){	return (mode & flag) == flag;}static struct dlstatus *lookupStatus(const struct stat *sbuf){	struct dlstatus *dls = stqueue;	debug("looking for status");	while (dls && ( /* isFlagSet(dls->mode, RTLD_UNSHARED) */ 0				   || sbuf->st_dev != dls->device || sbuf->st_ino != dls->inode))		dls = dls->next;	return dls;}static void insertStatus(struct dlstatus *dls, const struct stat *sbuf){	debug("inserting status");	dls->inode = sbuf->st_ino;	dls->device = sbuf->st_dev;	dls->refs = 0;	dls->mode = 0;	if ((dls->flags & DL_IN_LIST) == 0)	{		dls->next = stqueue;		stqueue = dls;		dls->flags |= DL_IN_LIST;	}}static struct dlstatus *allocStatus(){	struct dlstatus *dls;#ifdef REUSE_STATUS	dls = stqueue;	while (dls && dls->module)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -