Xcode has trouble compiling different files with the same name for two architectures
authorSam Lantinga
Wed, 10 May 2006 06:12:45 +0000
changeset 1801e308d020d315
parent 1800 cc6bea4bb90d
child 1802 54f63955dc1f
Xcode has trouble compiling different files with the same name for two architectures
src/loadso/macosx/SDL_dlcompat.c
src/loadso/macosx/SDL_sysloadso.c
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/loadso/macosx/SDL_dlcompat.c	Wed May 10 06:12:45 2006 +0000
     1.3 @@ -0,0 +1,1407 @@
     1.4 +/*
     1.5 +    SDL - Simple DirectMedia Layer
     1.6 +    Copyright (C) 1997-2006 Sam Lantinga
     1.7 +
     1.8 +    This library is free software; you can redistribute it and/or
     1.9 +    modify it under the terms of the GNU Lesser General Public
    1.10 +    License as published by the Free Software Foundation; either
    1.11 +    version 2.1 of the License, or (at your option) any later version.
    1.12 +
    1.13 +    This library is distributed in the hope that it will be useful,
    1.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.16 +    Lesser General Public License for more details.
    1.17 +
    1.18 +    You should have received a copy of the GNU Lesser General Public
    1.19 +    License along with this library; if not, write to the Free Software
    1.20 +    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    1.21 +
    1.22 +    Sam Lantinga
    1.23 +    slouken@libsdl.org
    1.24 +*/
    1.25 +#include "SDL_config.h"
    1.26 +
    1.27 +#ifdef SDL_LOADSO_DLCOMPAT
    1.28 +
    1.29 +/* Please note that dlcompat apparently ships in current Mac OS X versions
    1.30 + *  as a system library that provides compatibility with the Unix "dlopen"
    1.31 + *  interface. In order to allow SDL to work on older OS X releases and also
    1.32 + *  not conflict with the system lib on newer versions, we include dlcompat
    1.33 + *  in SDL and change the symbols to prevent symbol clash with any existing
    1.34 + *  system libraries.  --ryan.
    1.35 + */
    1.36 +
    1.37 +/* here is the dlcompat license: */
    1.38 +
    1.39 +/*
    1.40 +Copyright (c) 2002 Jorge Acereda  <jacereda@users.sourceforge.net> &
    1.41 +                   Peter O'Gorman <ogorman@users.sourceforge.net>
    1.42 +                   
    1.43 +Portions may be copyright others, see the AUTHORS file included with this
    1.44 +distribution.
    1.45 +
    1.46 +Maintained by Peter O'Gorman <ogorman@users.sourceforge.net>
    1.47 +
    1.48 +Bug Reports and other queries should go to <ogorman@users.sourceforge.net>
    1.49 +
    1.50 +Permission is hereby granted, free of charge, to any person obtaining
    1.51 +a copy of this software and associated documentation files (the
    1.52 +"Software"), to deal in the Software without restriction, including
    1.53 +without limitation the rights to use, copy, modify, merge, publish,
    1.54 +distribute, sublicense, and/or sell copies of the Software, and to
    1.55 +permit persons to whom the Software is furnished to do so, subject to
    1.56 +the following conditions:
    1.57 +
    1.58 +The above copyright notice and this permission notice shall be
    1.59 +included in all copies or substantial portions of the Software.
    1.60 +
    1.61 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    1.62 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    1.63 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    1.64 +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    1.65 +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    1.66 +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    1.67 +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    1.68 +*/
    1.69 +
    1.70 +#include <pthread.h>
    1.71 +#include <sys/types.h>
    1.72 +#include <sys/stat.h>
    1.73 +#include <stdarg.h>
    1.74 +#include <limits.h>
    1.75 +#include <mach-o/dyld.h>
    1.76 +#include <mach-o/nlist.h>
    1.77 +#include <mach-o/getsect.h>
    1.78 +
    1.79 +#include "SDL_stdinc.h"
    1.80 +
    1.81 +/* Just playing to see if it would compile with the freebsd headers, it does,
    1.82 + * but because of the different values for RTLD_LOCAL etc, it would break binary
    1.83 + * compat... oh well
    1.84 + */
    1.85 +#ifndef __BSD_VISIBLE
    1.86 +#define __BSD_VISIBLE 1
    1.87 +#endif
    1.88 +
    1.89 +/*include "dlfcn.h"*/
    1.90 +#ifdef __cplusplus
    1.91 +extern "C" {
    1.92 +#endif
    1.93 +
    1.94 +#if defined (__GNUC__) && __GNUC__ > 3
    1.95 +#define dl_restrict __restrict
    1.96 +#else
    1.97 +#define dl_restrict
    1.98 +#endif
    1.99 +
   1.100 +#if 0
   1.101 +#ifndef _POSIX_SOURCE
   1.102 +/*
   1.103 + * Structure filled in by dladdr().
   1.104 + */
   1.105 +typedef struct SDL_OSX_dl_info {
   1.106 +        const char      *dli_fname;     /* Pathname of shared object */
   1.107 +        void            *dli_fbase;     /* Base address of shared object */
   1.108 +        const char      *dli_sname;     /* Name of nearest symbol */
   1.109 +        void            *dli_saddr;     /* Address of nearest symbol */
   1.110 +} SDL_OSX_Dl_info;
   1.111 +
   1.112 +static int SDL_OSX_dladdr(const void * dl_restrict, SDL_OSX_Dl_info * dl_restrict);
   1.113 +#endif /* ! _POSIX_SOURCE */
   1.114 +#endif /* 0 */
   1.115 +
   1.116 +static int SDL_OSX_dlclose(void * handle);
   1.117 +static const char * SDL_OSX_dlerror(void);
   1.118 +static void * SDL_OSX_dlopen(const char *path, int mode);
   1.119 +static void * SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol);
   1.120 +
   1.121 +#define RTLD_LAZY	0x1
   1.122 +#define RTLD_NOW	0x2
   1.123 +#define RTLD_LOCAL	0x4
   1.124 +#define RTLD_GLOBAL	0x8
   1.125 +
   1.126 +#ifndef _POSIX_SOURCE
   1.127 +#define RTLD_NOLOAD	0x10
   1.128 +#define RTLD_NODELETE	0x80
   1.129 +
   1.130 +/*
   1.131 + * Special handle arguments for SDL_OSX_dlsym().
   1.132 + */
   1.133 +#define	RTLD_NEXT		((void *) -1)	/* Search subsequent objects. */
   1.134 +#define	RTLD_DEFAULT	((void *) -2)	/* Use default search algorithm. */
   1.135 +#endif /* ! _POSIX_SOURCE */
   1.136 +
   1.137 +#ifdef __cplusplus
   1.138 +}
   1.139 +#endif
   1.140 +
   1.141 +#ifndef dl_restrict
   1.142 +#define dl_restrict __restrict
   1.143 +#endif
   1.144 +/* This is not available on 10.1 */
   1.145 +#ifndef LC_LOAD_WEAK_DYLIB
   1.146 +#define	LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
   1.147 +#endif
   1.148 +
   1.149 +/* With this stuff here, this thing may actually compile/run on 10.0 systems
   1.150 + * Not that I have a 10.0 system to test it on anylonger
   1.151 + */
   1.152 +#ifndef LC_REQ_DYLD
   1.153 +#define LC_REQ_DYLD 0x80000000
   1.154 +#endif
   1.155 +#ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
   1.156 +#define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4
   1.157 +#endif
   1.158 +#ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR
   1.159 +#define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
   1.160 +#endif
   1.161 +#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
   1.162 +#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0
   1.163 +#endif
   1.164 +#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
   1.165 +#define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
   1.166 +#endif
   1.167 +/* These symbols will be looked for in dyld */
   1.168 +static const struct mach_header *(*dyld_NSAddImage) (const char *, unsigned long) = 0;
   1.169 +static int (*dyld_NSIsSymbolNameDefinedInImage) (const struct mach_header *, const char *) = 0;
   1.170 +static NSSymbol(*dyld_NSLookupSymbolInImage)
   1.171 +	(const struct mach_header *, const char *, unsigned long) = 0;
   1.172 +
   1.173 +/* Define this to make dlcompat reuse data block. This way in theory we save
   1.174 + * a little bit of overhead. However we then couldn't correctly catch excess
   1.175 + * calls to SDL_OSX_dlclose(). Hence we don't use this feature
   1.176 + */
   1.177 +#undef REUSE_STATUS
   1.178 +
   1.179 +/* Size of the internal error message buffer (used by dlerror()) */
   1.180 +#define ERR_STR_LEN			251
   1.181 +
   1.182 +/* Maximum number of search paths supported by getSearchPath */
   1.183 +#define MAX_SEARCH_PATHS	32
   1.184 +
   1.185 +
   1.186 +#define MAGIC_DYLIB_OFI ((NSObjectFileImage) 'DYOF')
   1.187 +#define MAGIC_DYLIB_MOD ((NSModule) 'DYMO')
   1.188 +
   1.189 +/* internal flags */
   1.190 +#define DL_IN_LIST 0x01
   1.191 +
   1.192 +/* our mutex */
   1.193 +static pthread_mutex_t dlcompat_mutex;
   1.194 +/* Our thread specific storage
   1.195 + */
   1.196 +static pthread_key_t dlerror_key;
   1.197 +
   1.198 +struct dlthread
   1.199 +{
   1.200 +	int lockcnt;
   1.201 +	unsigned char errset;
   1.202 +	char errstr[ERR_STR_LEN];
   1.203 +};
   1.204 +
   1.205 +/* This is our central data structure. Whenever a module is loaded via
   1.206 + * SDL_OSX_dlopen(), we create such a struct.
   1.207 + */
   1.208 +struct dlstatus
   1.209 +{
   1.210 +	struct dlstatus *next;		/* pointer to next element in the linked list */
   1.211 +	NSModule module;
   1.212 +	const struct mach_header *lib;
   1.213 +	int refs;					/* reference count */
   1.214 +	int mode;					/* mode in which this module was loaded */
   1.215 +	dev_t device;
   1.216 +	ino_t inode;
   1.217 +	int flags;					/* Any internal flags we may need */
   1.218 +};
   1.219 +
   1.220 +/* Head node of the dlstatus list */
   1.221 +static struct dlstatus mainStatus = { 0, MAGIC_DYLIB_MOD, NULL, -1, RTLD_GLOBAL, 0, 0, 0 };
   1.222 +static struct dlstatus *stqueue = &mainStatus;
   1.223 +
   1.224 +
   1.225 +/* Storage for the last error message (used by dlerror()) */
   1.226 +/* static char err_str[ERR_STR_LEN]; */
   1.227 +/* static int err_filled = 0; */
   1.228 +
   1.229 +/* Prototypes to internal functions */
   1.230 +static void debug(const char *fmt, ...);
   1.231 +static void error(const char *str, ...);
   1.232 +static const char *safegetenv(const char *s);
   1.233 +static const char *searchList(void);
   1.234 +static const char *getSearchPath(int i);
   1.235 +static const char *getFullPath(int i, const char *file);
   1.236 +static const struct stat *findFile(const char *file, const char **fullPath);
   1.237 +static int isValidStatus(struct dlstatus *status);
   1.238 +static inline int isFlagSet(int mode, int flag);
   1.239 +static struct dlstatus *lookupStatus(const struct stat *sbuf);
   1.240 +static void insertStatus(struct dlstatus *dls, const struct stat *sbuf);
   1.241 +static int promoteLocalToGlobal(struct dlstatus *dls);
   1.242 +static void *reference(struct dlstatus *dls, int mode);
   1.243 +static void *dlsymIntern(struct dlstatus *dls, const char *symbol, int canSetError);
   1.244 +static struct dlstatus *allocStatus(void);
   1.245 +static struct dlstatus *loadModule(const char *path, const struct stat *sbuf, int mode);
   1.246 +static NSSymbol search_linked_libs(const struct mach_header *mh, const char *symbol);
   1.247 +static const char *get_lib_name(const struct mach_header *mh);
   1.248 +static const struct mach_header *get_mach_header_from_NSModule(NSModule mod);
   1.249 +static void dlcompat_init_func(void);
   1.250 +static inline void dlcompat_init_check(void);
   1.251 +static inline void dolock(void);
   1.252 +static inline void dounlock(void);
   1.253 +static void dlerrorfree(void *data);
   1.254 +static void resetdlerror(void);
   1.255 +static const struct mach_header *my_find_image(const char *name);
   1.256 +static const struct mach_header *image_for_address(const void *address);
   1.257 +static inline char *dyld_error_str(void);
   1.258 +
   1.259 +#if FINK_BUILD
   1.260 +/* Two Global Functions */
   1.261 +static void *dlsym_prepend_underscore(void *handle, const char *symbol);
   1.262 +static void *dlsym_auto_underscore(void *handle, const char *symbol);
   1.263 +
   1.264 +/* And their _intern counterparts */
   1.265 +static void *dlsym_prepend_underscore_intern(void *handle, const char *symbol);
   1.266 +static void *dlsym_auto_underscore_intern(void *handle, const char *symbol);
   1.267 +#endif
   1.268 +
   1.269 +/* Functions */
   1.270 +
   1.271 +static void debug(const char *fmt, ...)
   1.272 +{
   1.273 +#if DEBUG > 1
   1.274 +	va_list arg;
   1.275 +	va_start(arg, fmt);
   1.276 +	fprintf(stderr, "DLDEBUG: ");
   1.277 +	vfprintf(stderr, fmt, arg);
   1.278 +	fprintf(stderr, "\n");
   1.279 +	fflush(stderr);
   1.280 +	va_end(arg);
   1.281 +#endif
   1.282 +}
   1.283 +
   1.284 +static void error(const char *str, ...)
   1.285 +{
   1.286 +	va_list arg;
   1.287 +	struct dlthread  *tss;
   1.288 +	char * err_str;
   1.289 +	va_start(arg, str);
   1.290 +	tss = pthread_getspecific(dlerror_key);
   1.291 +	err_str = tss->errstr;
   1.292 +	SDL_strlcpy(err_str, "dlcompat: ", ERR_STR_LEN);
   1.293 +	vsnprintf(err_str + 10, ERR_STR_LEN - 10, str, arg);
   1.294 +	va_end(arg);
   1.295 +	debug("ERROR: %s\n", err_str);
   1.296 +	tss->errset = 1;
   1.297 +}
   1.298 +
   1.299 +static void warning(const char *str)
   1.300 +{
   1.301 +#if DEBUG > 0
   1.302 +	fprintf(stderr, "WARNING: dlcompat: %s\n", str);
   1.303 +#endif
   1.304 +}
   1.305 +
   1.306 +static const char *safegetenv(const char *s)
   1.307 +{
   1.308 +	const char *ss = SDL_getenv(s);
   1.309 +	return ss ? ss : "";
   1.310 +}
   1.311 +
   1.312 +/* because this is only used for debugging and error reporting functions, we
   1.313 + * don't really care about how elegant it is... it could use the load
   1.314 + * commands to find the install name of the library, but...
   1.315 + */
   1.316 +static const char *get_lib_name(const struct mach_header *mh)
   1.317 +{
   1.318 +	unsigned long count = _dyld_image_count();
   1.319 +	unsigned long i;
   1.320 +	const char *val = NULL;
   1.321 +	if (mh)
   1.322 +	{
   1.323 +		for (i = 0; i < count; i++)
   1.324 +		{
   1.325 +			if (mh == _dyld_get_image_header(i))
   1.326 +			{
   1.327 +				val = _dyld_get_image_name(i);
   1.328 +				break;
   1.329 +			}
   1.330 +		}
   1.331 +	}
   1.332 +	return val;
   1.333 +}
   1.334 +
   1.335 +/* Returns the mach_header for the module bu going through all the loaded images
   1.336 + * and finding the one with the same name as the module. There really ought to be
   1.337 + * an api for doing this, would be faster, but there isn't one right now
   1.338 + */
   1.339 +static const struct mach_header *get_mach_header_from_NSModule(NSModule mod)
   1.340 +{
   1.341 +	const char *mod_name = NSNameOfModule(mod);
   1.342 +	const struct mach_header *mh = NULL;
   1.343 +	unsigned long count = _dyld_image_count();
   1.344 +	unsigned long i;
   1.345 +	debug("Module name: %s", mod_name);
   1.346 +	for (i = 0; i < count; i++)
   1.347 +	{
   1.348 +		if (!SDL_strcmp(mod_name, _dyld_get_image_name(i)))
   1.349 +		{
   1.350 +			mh = _dyld_get_image_header(i);
   1.351 +			break;
   1.352 +		}
   1.353 +	}
   1.354 +	return mh;
   1.355 +}
   1.356 +
   1.357 +
   1.358 +/* Compute and return a list of all directories that we should search when
   1.359 + * trying to locate a module. We first look at the values of LD_LIBRARY_PATH
   1.360 + * and DYLD_LIBRARY_PATH, and then finally fall back to looking into
   1.361 + * /usr/lib and /lib. Since both of the environments variables can contain a
   1.362 + * list of colon seperated paths, we simply concat them and the two other paths
   1.363 + * into one big string, which we then can easily parse.
   1.364 + * Splitting this string into the actual path list is done by getSearchPath()
   1.365 + */
   1.366 +static const char *searchList()
   1.367 +{
   1.368 +	size_t buf_size;
   1.369 +	static char *buf=NULL;
   1.370 +	const char *ldlp = safegetenv("LD_LIBRARY_PATH");
   1.371 +	const char *dyldlp = safegetenv("DYLD_LIBRARY_PATH");
   1.372 +	const char *stdpath = SDL_getenv("DYLD_FALLBACK_LIBRARY_PATH");
   1.373 +	if (!stdpath)
   1.374 +		stdpath = "/usr/local/lib:/lib:/usr/lib";
   1.375 +	if (!buf)
   1.376 +	{	
   1.377 +		buf_size = SDL_strlen(ldlp) + SDL_strlen(dyldlp) + SDL_strlen(stdpath) + 4;
   1.378 +		buf = SDL_malloc(buf_size);
   1.379 +		SDL_snprintf(buf, buf_size, "%s%s%s%s%s%c", dyldlp, (dyldlp[0] ? ":" : ""), ldlp, (ldlp[0] ? ":" : ""),
   1.380 +				 stdpath, '\0');
   1.381 +	}
   1.382 +	return buf;
   1.383 +}
   1.384 +
   1.385 +/* Returns the ith search path from the list as computed by searchList() */
   1.386 +static const char *getSearchPath(int i)
   1.387 +{
   1.388 +	static const char *list = 0;
   1.389 +	static char **path = (char **)0;
   1.390 +	static int end = 0;
   1.391 +	static int numsize = MAX_SEARCH_PATHS;
   1.392 +	static char **tmp;
   1.393 +	/* So we can call SDL_free() in the "destructor" we use i=-1 to return the alloc'd array */
   1.394 +	if (i == -1)
   1.395 +	{
   1.396 +		return (const char*)path;
   1.397 +	}
   1.398 +	if (!path)
   1.399 +	{
   1.400 +		path = (char **)SDL_calloc(MAX_SEARCH_PATHS, sizeof(char **));
   1.401 +	}
   1.402 +	if (!list && !end)
   1.403 +		list = searchList();
   1.404 +	if (i >= (numsize))
   1.405 +	{
   1.406 +		debug("Increasing size for long PATH");
   1.407 +		tmp = (char **)SDL_calloc((MAX_SEARCH_PATHS + numsize), sizeof(char **));
   1.408 +		if (tmp)
   1.409 +		{
   1.410 +			SDL_memcpy(tmp, path, sizeof(char **) * numsize);
   1.411 +			SDL_free(path);
   1.412 +			path = tmp;
   1.413 +			numsize += MAX_SEARCH_PATHS;
   1.414 +		}
   1.415 +		else
   1.416 +		{
   1.417 +			return 0;
   1.418 +		}
   1.419 +	}
   1.420 +
   1.421 +	while (!path[i] && !end)
   1.422 +	{
   1.423 +		path[i] = strsep((char **)&list, ":");
   1.424 +
   1.425 +		if (path[i][0] == 0)
   1.426 +			path[i] = 0;
   1.427 +		end = (list == 0);
   1.428 +	}
   1.429 +	return path[i];
   1.430 +}
   1.431 +
   1.432 +static const char *getFullPath(int i, const char *file)
   1.433 +{
   1.434 +	static char buf[PATH_MAX];
   1.435 +	const char *path = getSearchPath(i);
   1.436 +	if (path)
   1.437 +	{
   1.438 +		SDL_snprintf(buf, PATH_MAX, "%s/%s", path, file);
   1.439 +	}
   1.440 +	return path ? buf : 0;
   1.441 +}
   1.442 +
   1.443 +/* Given a file name, try to determine the full path for that file. Starts
   1.444 + * its search in the current directory, and then tries all paths in the 
   1.445 + * search list in the order they are specified there.
   1.446 + */
   1.447 +static const struct stat *findFile(const char *file, const char **fullPath)
   1.448 +{
   1.449 +	int i = 0;
   1.450 +	static struct stat sbuf;
   1.451 +	char *fileName;
   1.452 +	debug("finding file %s", file);
   1.453 +	*fullPath = file;
   1.454 +	if (0 == stat(file, &sbuf))
   1.455 +		return &sbuf;
   1.456 +	if (SDL_strchr(file, '/'))
   1.457 +		return 0;				/* If the path had a / we don't look in env var places */
   1.458 +	fileName = NULL;
   1.459 +	if (!fileName)
   1.460 +		fileName = (char *)file;
   1.461 +	while ((*fullPath = getFullPath(i++, fileName)))
   1.462 +	{
   1.463 +		if (0 == stat(*fullPath, &sbuf))
   1.464 +			return &sbuf;
   1.465 +	}
   1.466 +	;
   1.467 +	return 0;
   1.468 +}
   1.469 +
   1.470 +/* Determine whether a given dlstatus is valid or not */
   1.471 +static int isValidStatus(struct dlstatus *status)
   1.472 +{
   1.473 +	/* Walk the list to verify status is contained in it */
   1.474 +	struct dlstatus *dls = stqueue;
   1.475 +	while (dls && status != dls)
   1.476 +		dls = dls->next;
   1.477 +	if (dls == 0)
   1.478 +		error("invalid handle");
   1.479 +	else if ((dls->module == 0) || (dls->refs == 0))
   1.480 +		error("handle to closed library");
   1.481 +	else
   1.482 +		return TRUE;
   1.483 +	return FALSE;
   1.484 +}
   1.485 +
   1.486 +static inline int isFlagSet(int mode, int flag)
   1.487 +{
   1.488 +	return (mode & flag) == flag;
   1.489 +}
   1.490 +
   1.491 +static struct dlstatus *lookupStatus(const struct stat *sbuf)
   1.492 +{
   1.493 +	struct dlstatus *dls = stqueue;
   1.494 +	debug("looking for status");
   1.495 +	while (dls && ( /* isFlagSet(dls->mode, RTLD_UNSHARED) */ 0
   1.496 +				   || sbuf->st_dev != dls->device || sbuf->st_ino != dls->inode))
   1.497 +		dls = dls->next;
   1.498 +	return dls;
   1.499 +}
   1.500 +
   1.501 +static void insertStatus(struct dlstatus *dls, const struct stat *sbuf)
   1.502 +{
   1.503 +	debug("inserting status");
   1.504 +	dls->inode = sbuf->st_ino;
   1.505 +	dls->device = sbuf->st_dev;
   1.506 +	dls->refs = 0;
   1.507 +	dls->mode = 0;
   1.508 +	if ((dls->flags & DL_IN_LIST) == 0)
   1.509 +	{
   1.510 +		dls->next = stqueue;
   1.511 +		stqueue = dls;
   1.512 +		dls->flags |= DL_IN_LIST;
   1.513 +	}
   1.514 +}
   1.515 +
   1.516 +static struct dlstatus *allocStatus()
   1.517 +{
   1.518 +	struct dlstatus *dls;
   1.519 +#ifdef REUSE_STATUS
   1.520 +	dls = stqueue;
   1.521 +	while (dls && dls->module)
   1.522 +		dls = dls->next;
   1.523 +	if (!dls)
   1.524 +#endif
   1.525 +		dls = SDL_calloc(sizeof(*dls),1);
   1.526 +	return dls;
   1.527 +}
   1.528 +
   1.529 +static int promoteLocalToGlobal(struct dlstatus *dls)
   1.530 +{
   1.531 +	static int (*p) (NSModule module) = 0;
   1.532 +	debug("promoting");
   1.533 +	if (!p)
   1.534 +		_dyld_func_lookup("__dyld_NSMakePrivateModulePublic", (void **)&p);
   1.535 +	return (dls->module == MAGIC_DYLIB_MOD) || (p && p(dls->module));
   1.536 +}
   1.537 +
   1.538 +static void *reference(struct dlstatus *dls, int mode)
   1.539 +{
   1.540 +	if (dls)
   1.541 +	{
   1.542 +		if (dls->module == MAGIC_DYLIB_MOD && isFlagSet(mode, RTLD_LOCAL))
   1.543 +		{
   1.544 +			warning("trying to open a .dylib with RTLD_LOCAL");
   1.545 +			error("unable to open a .dylib with RTLD_LOCAL");
   1.546 +			return NULL;
   1.547 +		}
   1.548 +		if (isFlagSet(mode, RTLD_GLOBAL) &&
   1.549 +			!isFlagSet(dls->mode, RTLD_GLOBAL) && !promoteLocalToGlobal(dls))
   1.550 +		{
   1.551 +			error("unable to promote local module to global");
   1.552 +			return NULL;
   1.553 +		}
   1.554 +		dls->mode |= mode;
   1.555 +		dls->refs++;
   1.556 +	}
   1.557 +	else
   1.558 +		debug("reference called with NULL argument");
   1.559 +
   1.560 +	return dls;
   1.561 +}
   1.562 +
   1.563 +static const struct mach_header *my_find_image(const char *name)
   1.564 +{
   1.565 +	const struct mach_header *mh = 0;
   1.566 +	const char *id = NULL;
   1.567 +	int i = _dyld_image_count();
   1.568 +	int j;
   1.569 +	mh = (struct mach_header *)
   1.570 +		dyld_NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED |
   1.571 +						NSADDIMAGE_OPTION_RETURN_ON_ERROR);
   1.572 +	if (!mh)
   1.573 +	{
   1.574 +		for (j = 0; j < i; j++)
   1.575 +		{
   1.576 +			id = _dyld_get_image_name(j);
   1.577 +			if (!SDL_strcmp(id, name))
   1.578 +			{
   1.579 +				mh = _dyld_get_image_header(j);
   1.580 +				break;
   1.581 +			}
   1.582 +		}
   1.583 +	}
   1.584 +	return mh;
   1.585 +}
   1.586 +
   1.587 +/*
   1.588 + * dyld adds libraries by first adding the directly dependant libraries in link order, and
   1.589 + * then adding the dependencies for those libraries, so we should do the same... but we don't
   1.590 + * bother adding the extra dependencies, if the symbols are neither in the loaded image nor
   1.591 + * any of it's direct dependencies, then it probably isn't there.
   1.592 + */
   1.593 +static NSSymbol search_linked_libs(const struct mach_header * mh, const char *symbol)
   1.594 +{
   1.595 +	unsigned int n;
   1.596 +	struct load_command *lc = 0;
   1.597 +	struct mach_header *wh;
   1.598 +	NSSymbol nssym = 0;
   1.599 +	if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage)
   1.600 +	{
   1.601 +		lc = (struct load_command *)((char *)mh + sizeof(struct mach_header));
   1.602 +		for (n = 0; n < mh->ncmds; n++, lc = (struct load_command *)((char *)lc + lc->cmdsize))
   1.603 +		{
   1.604 +			if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd))
   1.605 +			{
   1.606 +				if ((wh = (struct mach_header *)
   1.607 +					 my_find_image((char *)(((struct dylib_command *)lc)->dylib.name.offset +
   1.608 +											(char *)lc))))
   1.609 +				{
   1.610 +					if (dyld_NSIsSymbolNameDefinedInImage(wh, symbol))
   1.611 +					{
   1.612 +						nssym = dyld_NSLookupSymbolInImage(wh,
   1.613 +														   symbol,
   1.614 +														   NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
   1.615 +														   NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
   1.616 +						break;
   1.617 +					}
   1.618 +				}
   1.619 +			}
   1.620 +		}
   1.621 +		if ((!nssym) && NSIsSymbolNameDefined(symbol))
   1.622 +		{
   1.623 +			/* I've never seen this debug message...*/
   1.624 +			debug("Symbol \"%s\" is defined but was not found", symbol);
   1.625 +		}
   1.626 +	}
   1.627 +	return nssym;
   1.628 +}
   1.629 +
   1.630 +/* Up to the caller to SDL_free() returned string */
   1.631 +static inline char *dyld_error_str()
   1.632 +{
   1.633 +	NSLinkEditErrors dylder;
   1.634 +	int dylderno;
   1.635 +	const char *dylderrstr;
   1.636 +	const char *dyldfile;
   1.637 +	char* retStr = NULL;
   1.638 +	NSLinkEditError(&dylder, &dylderno, &dyldfile, &dylderrstr);
   1.639 +	if (dylderrstr && *dylderrstr)
   1.640 +	{
   1.641 +		retStr = SDL_strdup(dylderrstr);
   1.642 +	}
   1.643 +	return retStr;
   1.644 +}
   1.645 +
   1.646 +static void *dlsymIntern(struct dlstatus *dls, const char *symbol, int canSetError)
   1.647 +{
   1.648 +  NSSymbol nssym = 0;
   1.649 +#ifdef __GCC__  
   1.650 +	void *caller = __builtin_return_address(1);	/* Be *very* careful about inlining */
   1.651 +#else
   1.652 +	void *caller = NULL;
   1.653 +#endif
   1.654 +	const struct mach_header *caller_mh = 0;
   1.655 +	char *savedErrorStr = NULL;
   1.656 +	resetdlerror();
   1.657 +#ifndef RTLD_SELF
   1.658 +#define	RTLD_SELF		((void *) -3)
   1.659 +#endif
   1.660 +	if (NULL == dls)
   1.661 +		dls = RTLD_SELF;
   1.662 +	if ((RTLD_NEXT == dls) || (RTLD_SELF == dls))
   1.663 +	{
   1.664 +		if (dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage && caller)
   1.665 +		  {
   1.666 +			caller_mh = image_for_address(caller);
   1.667 +			if (RTLD_SELF == dls)
   1.668 +			{
   1.669 +				/* FIXME: We should be using the NSModule api, if SELF is an MH_BUNDLE
   1.670 +				 * But it appears to work anyway, and looking at the code in dyld_libfuncs.c
   1.671 +				 * this is acceptable.
   1.672 +				 */
   1.673 +				if (dyld_NSIsSymbolNameDefinedInImage(caller_mh, symbol))
   1.674 +				{
   1.675 +					nssym = dyld_NSLookupSymbolInImage(caller_mh,
   1.676 +													   symbol,
   1.677 +													   NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
   1.678 +													   NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
   1.679 +				}
   1.680 +			}
   1.681 +			if (!nssym)
   1.682 +			{
   1.683 +				if (RTLD_SELF == dls)
   1.684 +					savedErrorStr = dyld_error_str();
   1.685 +				nssym = search_linked_libs(caller_mh, symbol);
   1.686 +			}
   1.687 +		}
   1.688 +		else
   1.689 +		{
   1.690 +			if (canSetError)
   1.691 +				error("RTLD_SELF and RTLD_NEXT are not supported");
   1.692 +			return NULL;
   1.693 +		}
   1.694 +	}
   1.695 +	if (!nssym)
   1.696 +	{
   1.697 +
   1.698 +		if (RTLD_DEFAULT == dls)
   1.699 +		{
   1.700 +			dls = &mainStatus;
   1.701 +		}
   1.702 +		if (!isValidStatus(dls))
   1.703 +			return NULL;
   1.704 +
   1.705 +		if (dls->module != MAGIC_DYLIB_MOD)
   1.706 +		{
   1.707 +			nssym = NSLookupSymbolInModule(dls->module, symbol);
   1.708 +			if (!nssym && NSIsSymbolNameDefined(symbol))
   1.709 +			{
   1.710 +				debug("Searching dependencies");
   1.711 +				savedErrorStr = dyld_error_str();
   1.712 +				nssym = search_linked_libs(get_mach_header_from_NSModule(dls->module), symbol);
   1.713 +			}
   1.714 +		}
   1.715 +		else if (dls->lib && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage)
   1.716 +		{
   1.717 +			if (dyld_NSIsSymbolNameDefinedInImage(dls->lib, symbol))
   1.718 +			{
   1.719 +				nssym = dyld_NSLookupSymbolInImage(dls->lib,
   1.720 +												   symbol,
   1.721 +												   NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
   1.722 +												   NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
   1.723 +			}
   1.724 +			else if (NSIsSymbolNameDefined(symbol))
   1.725 +			{
   1.726 +				debug("Searching dependencies");
   1.727 +				savedErrorStr = dyld_error_str();
   1.728 +				nssym = search_linked_libs(dls->lib, symbol);
   1.729 +			}
   1.730 +		}
   1.731 +		else if (dls->module == MAGIC_DYLIB_MOD)
   1.732 +		{
   1.733 +			/* Global context, use NSLookupAndBindSymbol */
   1.734 +			if (NSIsSymbolNameDefined(symbol))
   1.735 +			{
   1.736 +				/* There doesn't seem to be a return on error option for this call???
   1.737 +				   this is potentially broken, if binding fails, it will improperly
   1.738 +				   exit the application. */
   1.739 +				nssym = NSLookupAndBindSymbol(symbol);
   1.740 +			}
   1.741 +			else
   1.742 +			{
   1.743 +				if (savedErrorStr)
   1.744 +					SDL_free(savedErrorStr);			
   1.745 +				savedErrorStr = SDL_malloc(256);
   1.746 +				SDL_snprintf(savedErrorStr, 256, "Symbol \"%s\" not in global context",symbol);	
   1.747 +			}
   1.748 +		}
   1.749 +	}
   1.750 +	/* Error reporting */
   1.751 +	if (!nssym)
   1.752 +	{
   1.753 +		if (!savedErrorStr || !SDL_strlen(savedErrorStr))
   1.754 +		{
   1.755 +			if (savedErrorStr)
   1.756 +				SDL_free(savedErrorStr);
   1.757 +			savedErrorStr = SDL_malloc(256);
   1.758 +			SDL_snprintf(savedErrorStr, 256,"Symbol \"%s\" not found",symbol);
   1.759 +		}
   1.760 +		if (canSetError)
   1.761 +		{
   1.762 +			error(savedErrorStr);
   1.763 +		}
   1.764 +		else
   1.765 +		{
   1.766 +			debug(savedErrorStr);
   1.767 +		}
   1.768 +		if (savedErrorStr)
   1.769 +			SDL_free(savedErrorStr);
   1.770 +		return NULL;
   1.771 +	}
   1.772 +	return NSAddressOfSymbol(nssym);
   1.773 +}
   1.774 +
   1.775 +static struct dlstatus *loadModule(const char *path, const struct stat *sbuf, int mode)
   1.776 +{
   1.777 +	NSObjectFileImage ofi = 0;
   1.778 +	NSObjectFileImageReturnCode ofirc;
   1.779 +	struct dlstatus *dls;
   1.780 +	NSLinkEditErrors ler;
   1.781 +	int lerno;
   1.782 +	const char *errstr;
   1.783 +	const char *file;
   1.784 +	void (*init) (void);
   1.785 +
   1.786 +	ofirc = NSCreateObjectFileImageFromFile(path, &ofi);
   1.787 +	switch (ofirc)
   1.788 +	{
   1.789 +		case NSObjectFileImageSuccess:
   1.790 +			break;
   1.791 +		case NSObjectFileImageInappropriateFile:
   1.792 +			if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage)
   1.793 +			{	
   1.794 +				if (isFlagSet(mode, RTLD_LOCAL))
   1.795 +				{
   1.796 +					warning("trying to open a .dylib with RTLD_LOCAL");
   1.797 +					error("unable to open this file with RTLD_LOCAL");
   1.798 +					return NULL;
   1.799 +				}
   1.800 +			}
   1.801 +			else
   1.802 +			{
   1.803 +				error("opening this file is unsupported on this system");
   1.804 +				return NULL;
   1.805 +			}
   1.806 +			break;
   1.807 +		case NSObjectFileImageFailure:
   1.808 +			error("object file setup failure");
   1.809 +			return NULL;
   1.810 +		case NSObjectFileImageArch:
   1.811 +			error("no object for this architecture");
   1.812 +			return NULL;
   1.813 +		case NSObjectFileImageFormat:
   1.814 +			error("bad object file format");
   1.815 +			return NULL;
   1.816 +		case NSObjectFileImageAccess:
   1.817 +			error("can't read object file");
   1.818 +			return NULL;
   1.819 +		default:
   1.820 +			error("unknown error from NSCreateObjectFileImageFromFile()");
   1.821 +			return NULL;
   1.822 +	}
   1.823 +	dls = lookupStatus(sbuf);
   1.824 +	if (!dls)
   1.825 +	{
   1.826 +		dls = allocStatus();
   1.827 +	}
   1.828 +	if (!dls)
   1.829 +	{
   1.830 +		error("unable to allocate memory");
   1.831 +		return NULL;
   1.832 +	}
   1.833 +	//	dls->lib = 0;
   1.834 +	if (ofirc == NSObjectFileImageInappropriateFile)
   1.835 +	{
   1.836 +		if ((dls->lib = dyld_NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR)))
   1.837 +		{
   1.838 +			debug("Dynamic lib loaded at %ld", dls->lib);
   1.839 +			ofi = MAGIC_DYLIB_OFI;
   1.840 +			dls->module = MAGIC_DYLIB_MOD;
   1.841 +			ofirc = NSObjectFileImageSuccess;
   1.842 +			/* Although it is possible with a bit of work to modify this so it works and
   1.843 +			   functions with RTLD_NOW, I don't deem it necessary at the moment */
   1.844 +		}
   1.845 +		if (!(dls->module))
   1.846 +		{
   1.847 +			NSLinkEditError(&ler, &lerno, &file, &errstr);
   1.848 +			if (!errstr || (!SDL_strlen(errstr)))
   1.849 +				error("Can't open this file type");
   1.850 +			else
   1.851 +				error(errstr);
   1.852 +			if ((dls->flags & DL_IN_LIST) == 0)
   1.853 +			{
   1.854 +				SDL_free(dls);
   1.855 +			}
   1.856 +			return NULL;
   1.857 +		}
   1.858 +	}
   1.859 +	else
   1.860 +	{
   1.861 +		dls->module = NSLinkModule(ofi, path,
   1.862 +								   NSLINKMODULE_OPTION_RETURN_ON_ERROR |
   1.863 +								   NSLINKMODULE_OPTION_PRIVATE |
   1.864 +								   (isFlagSet(mode, RTLD_NOW) ? NSLINKMODULE_OPTION_BINDNOW : 0));
   1.865 +		NSDestroyObjectFileImage(ofi);
   1.866 +		if (dls->module)
   1.867 +		{
   1.868 +			dls->lib = get_mach_header_from_NSModule(dls->module);
   1.869 +		}
   1.870 +	}
   1.871 +	if (!dls->module)
   1.872 +	{
   1.873 +		NSLinkEditError(&ler, &lerno, &file, &errstr);
   1.874 +		if ((dls->flags & DL_IN_LIST) == 0)
   1.875 +		{
   1.876 +			SDL_free(dls);
   1.877 +		}
   1.878 +		error(errstr);
   1.879 +		return NULL;
   1.880 +	}
   1.881 +
   1.882 +	insertStatus(dls, sbuf);
   1.883 +	dls = reference(dls, mode);
   1.884 +	if ((init = dlsymIntern(dls, "__init", 0)))
   1.885 +	{
   1.886 +		debug("calling _init()");
   1.887 +		init();
   1.888 +	}
   1.889 +	return dls;
   1.890 +}
   1.891 +
   1.892 +inline static void dlcompat_init_check(void)
   1.893 +{
   1.894 +	static pthread_mutex_t l = PTHREAD_MUTEX_INITIALIZER;
   1.895 +	static int init_done = 0;
   1.896 +
   1.897 +	pthread_mutex_lock(&l);
   1.898 +	if (!init_done) {
   1.899 +		dlcompat_init_func();
   1.900 +		init_done = 1;
   1.901 +	}
   1.902 +	pthread_mutex_unlock(&l);
   1.903 +}
   1.904 +
   1.905 +static void dlcompat_init_func(void)
   1.906 +{
   1.907 +        _dyld_func_lookup("__dyld_NSAddImage", (void **)&dyld_NSAddImage);
   1.908 +	_dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",
   1.909 +			  (void **)&dyld_NSIsSymbolNameDefinedInImage);
   1.910 +	_dyld_func_lookup("__dyld_NSLookupSymbolInImage", (void **)&dyld_NSLookupSymbolInImage);
   1.911 +	if (pthread_mutex_init(&dlcompat_mutex, NULL))
   1.912 +	    exit(1);
   1.913 +	if (pthread_key_create(&dlerror_key, &dlerrorfree))
   1.914 +	    exit(1);
   1.915 +}
   1.916 +
   1.917 +static void resetdlerror()
   1.918 +{
   1.919 +	struct dlthread *tss;
   1.920 +	tss = pthread_getspecific(dlerror_key);
   1.921 +	tss->errset = 0;
   1.922 +}
   1.923 +
   1.924 +static void dlerrorfree(void *data)
   1.925 +{
   1.926 +	SDL_free(data);
   1.927 +}
   1.928 +
   1.929 +/* We kind of want a recursive lock here, but meet a little trouble
   1.930 + * because they are not available pre OS X 10.2, so we fake it
   1.931 + * using thread specific storage to keep a lock count
   1.932 + */ 
   1.933 +static inline void dolock(void)
   1.934 +{
   1.935 +	int err = 0;
   1.936 +	struct dlthread *tss;
   1.937 +	dlcompat_init_check();
   1.938 +	tss = pthread_getspecific(dlerror_key);
   1.939 +	if (!tss)
   1.940 +	{
   1.941 +		tss = SDL_malloc(sizeof(struct dlthread));
   1.942 +		tss->lockcnt = 0;
   1.943 +		tss->errset = 0;
   1.944 +		if (pthread_setspecific(dlerror_key, tss))
   1.945 +		{
   1.946 +			fprintf(stderr,"dlcompat: pthread_setspecific failed\n");
   1.947 +			exit(1);
   1.948 +		}
   1.949 +	}
   1.950 +	if (!tss->lockcnt)
   1.951 +		err = pthread_mutex_lock(&dlcompat_mutex);
   1.952 +	tss->lockcnt = tss->lockcnt +1;	
   1.953 +	if (err)
   1.954 +		exit(err);
   1.955 +}
   1.956 +
   1.957 +static inline void dounlock(void)
   1.958 +{
   1.959 +	int err = 0;
   1.960 +	struct dlthread *tss;
   1.961 +	tss = pthread_getspecific(dlerror_key);
   1.962 +	tss->lockcnt = tss->lockcnt -1;
   1.963 +	if (!tss->lockcnt)
   1.964 +		err = pthread_mutex_unlock(&dlcompat_mutex);
   1.965 +	if (err)
   1.966 +		exit(err);
   1.967 +}
   1.968 +
   1.969 +static void *SDL_OSX_dlopen(const char *path, int mode)
   1.970 +{
   1.971 +	const struct stat *sbuf;
   1.972 +	struct dlstatus *dls;
   1.973 +	const char *fullPath;
   1.974 +
   1.975 +	dolock();
   1.976 +	resetdlerror();
   1.977 +	if (!path)
   1.978 +	{
   1.979 +		dls = &mainStatus;
   1.980 +		goto dlopenok;
   1.981 +	}
   1.982 +	if (!(sbuf = findFile(path, &fullPath)))
   1.983 +	{
   1.984 +		error("file \"%s\" not found", path);
   1.985 +		goto dlopenerror;
   1.986 +	}
   1.987 +	/* Now checks that it hasn't been closed already */
   1.988 +	if ((dls = lookupStatus(sbuf)) && (dls->refs > 0))
   1.989 +	{
   1.990 +		/* debug("status found"); */
   1.991 +		dls = reference(dls, mode);
   1.992 +		goto dlopenok;
   1.993 +	}
   1.994 +#ifdef 	RTLD_NOLOAD
   1.995 +	if (isFlagSet(mode, RTLD_NOLOAD))
   1.996 +	{
   1.997 +		error("no existing handle and RTLD_NOLOAD specified");
   1.998 +		goto dlopenerror;
   1.999 +	}
  1.1000 +#endif
  1.1001 +	if (isFlagSet(mode, RTLD_LAZY) && isFlagSet(mode, RTLD_NOW))
  1.1002 +	{
  1.1003 +		error("how can I load something both RTLD_LAZY and RTLD_NOW?");
  1.1004 +		goto dlopenerror;
  1.1005 +	}
  1.1006 +	dls = loadModule(fullPath, sbuf, mode);
  1.1007 +	
  1.1008 +  dlopenok:
  1.1009 +	dounlock();
  1.1010 +	return (void *)dls;
  1.1011 +  dlopenerror:
  1.1012 +	dounlock();
  1.1013 +	return NULL;
  1.1014 +}
  1.1015 +
  1.1016 +#if !FINK_BUILD
  1.1017 +static void *SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol)
  1.1018 +{
  1.1019 +	int sym_len = SDL_strlen(symbol);
  1.1020 +	void *value = NULL;
  1.1021 +	char *malloc_sym = NULL;
  1.1022 +	dolock();
  1.1023 +	malloc_sym = SDL_malloc(sym_len + 2);
  1.1024 +	if (malloc_sym)
  1.1025 +	{
  1.1026 +		SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol);
  1.1027 +		value = dlsymIntern(handle, malloc_sym, 1);
  1.1028 +		SDL_free(malloc_sym);
  1.1029 +	}
  1.1030 +	else
  1.1031 +	{
  1.1032 +		error("Unable to allocate memory");
  1.1033 +		goto dlsymerror;
  1.1034 +	}
  1.1035 +	dounlock();
  1.1036 +	return value;
  1.1037 +  dlsymerror:
  1.1038 +	dounlock();
  1.1039 +	return NULL;
  1.1040 +}
  1.1041 +#endif
  1.1042 +
  1.1043 +#if FINK_BUILD
  1.1044 +
  1.1045 +static void *dlsym_prepend_underscore(void *handle, const char *symbol)
  1.1046 +{
  1.1047 +	void *answer;
  1.1048 +	dolock();
  1.1049 +	answer = dlsym_prepend_underscore_intern(handle, symbol);
  1.1050 +	dounlock();
  1.1051 +	return answer;
  1.1052 +}
  1.1053 +
  1.1054 +static void *dlsym_prepend_underscore_intern(void *handle, const char *symbol)
  1.1055 +{
  1.1056 +/*
  1.1057 + *	A quick and easy way for porting packages which call dlsym(handle,"sym")
  1.1058 + *	If the porter adds -Ddlsym=dlsym_prepend_underscore to the CFLAGS then
  1.1059 + *	this function will be called, and will add the required underscore.
  1.1060 + *	
  1.1061 + *	Note that I haven't figured out yet which should be "standard", prepend
  1.1062 + *	the underscore always, or not at all. These global functions need to go away
  1.1063 + *	for opendarwin.
  1.1064 + */
  1.1065 +	int sym_len = SDL_strlen(symbol);
  1.1066 +	void *value = NULL;
  1.1067 +	char *malloc_sym = NULL;
  1.1068 +	malloc_sym = SDL_malloc(sym_len + 2);
  1.1069 +	if (malloc_sym)
  1.1070 +	{
  1.1071 +		SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol);
  1.1072 +		value = dlsymIntern(handle, malloc_sym, 1);
  1.1073 +		SDL_free(malloc_sym);
  1.1074 +	}
  1.1075 +	else
  1.1076 +	{
  1.1077 +		error("Unable to allocate memory");
  1.1078 +	}
  1.1079 +	return value;
  1.1080 +}
  1.1081 +
  1.1082 +static void *dlsym_auto_underscore(void *handle, const char *symbol)
  1.1083 +{
  1.1084 +	void *answer;
  1.1085 +	dolock();
  1.1086 +	answer = dlsym_auto_underscore_intern(handle, symbol);
  1.1087 +	dounlock();
  1.1088 +	return answer;
  1.1089 +
  1.1090 +}
  1.1091 +static void *dlsym_auto_underscore_intern(void *handle, const char *symbol)
  1.1092 +{
  1.1093 +	struct dlstatus *dls = handle;
  1.1094 +	void *addr = 0;
  1.1095 +	addr = dlsymIntern(dls, symbol, 0);
  1.1096 +	if (!addr)
  1.1097 +		addr = dlsym_prepend_underscore_intern(handle, symbol);
  1.1098 +	return addr;
  1.1099 +}
  1.1100 +
  1.1101 +
  1.1102 +static void *SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol)
  1.1103 +{
  1.1104 +	struct dlstatus *dls = handle;
  1.1105 +	void *addr = 0;
  1.1106 +	dolock();
  1.1107 +	addr = dlsymIntern(dls, symbol, 1);
  1.1108 +	dounlock();
  1.1109 +	return addr;
  1.1110 +}
  1.1111 +#endif
  1.1112 +
  1.1113 +static int SDL_OSX_dlclose(void *handle)
  1.1114 +{
  1.1115 +	struct dlstatus *dls = handle;
  1.1116 +	dolock();
  1.1117 +	resetdlerror();
  1.1118 +	if (!isValidStatus(dls))
  1.1119 +	{
  1.1120 +		goto dlcloseerror;
  1.1121 +	}
  1.1122 +	if (dls->module == MAGIC_DYLIB_MOD)
  1.1123 +	{
  1.1124 +		const char *name;
  1.1125 +		if (!dls->lib)
  1.1126 +		{
  1.1127 +			name = "global context";
  1.1128 +		}
  1.1129 +		else
  1.1130 +		{
  1.1131 +			name = get_lib_name(dls->lib);
  1.1132 +		}
  1.1133 +		warning("trying to close a .dylib!");
  1.1134 +		error("Not closing \"%s\" - dynamic libraries cannot be closed", name);
  1.1135 +		goto dlcloseerror;
  1.1136 +	}
  1.1137 +	if (!dls->module)
  1.1138 +	{
  1.1139 +		error("module already closed");
  1.1140 +		goto dlcloseerror;
  1.1141 +	}
  1.1142 +	
  1.1143 +	if (dls->refs == 1)
  1.1144 +	{
  1.1145 +		unsigned long options = 0;
  1.1146 +		void (*fini) (void);
  1.1147 +		if ((fini = dlsymIntern(dls, "__fini", 0)))
  1.1148 +		{
  1.1149 +			debug("calling _fini()");
  1.1150 +			fini();
  1.1151 +		}
  1.1152 +		options |= NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
  1.1153 +#ifdef RTLD_NODELETE
  1.1154 +		if (isFlagSet(dls->mode, RTLD_NODELETE))
  1.1155 +			options |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
  1.1156 +#endif
  1.1157 +		if (!NSUnLinkModule(dls->module, options))
  1.1158 +		{
  1.1159 +			error("unable to unlink module");
  1.1160 +			goto dlcloseerror;
  1.1161 +		}
  1.1162 +		dls->refs--;
  1.1163 +		dls->module = 0;
  1.1164 +		/* Note: the dlstatus struct dls is neither removed from the list
  1.1165 +		 * nor is the memory it occupies freed. This shouldn't pose a 
  1.1166 +		 * problem in mostly all cases, though.
  1.1167 +		 */
  1.1168 +	}
  1.1169 +	dounlock();
  1.1170 +	return 0;
  1.1171 +  dlcloseerror:
  1.1172 +	dounlock();
  1.1173 +	return 1;
  1.1174 +}
  1.1175 +
  1.1176 +static const char *SDL_OSX_dlerror(void)
  1.1177 +{
  1.1178 +	struct dlthread  *tss;
  1.1179 +	const char * err_str = NULL;
  1.1180 +	dlcompat_init_check();
  1.1181 +	tss = pthread_getspecific(dlerror_key);
  1.1182 +	if (tss != NULL && tss->errset != 0) {
  1.1183 +		tss->errset = 0;	
  1.1184 +		err_str = tss->errstr;
  1.1185 +	}
  1.1186 +	return (err_str);
  1.1187 +}
  1.1188 +
  1.1189 +/* Given an address, return the mach_header for the image containing it
  1.1190 + * or zero if the given address is not contained in any loaded images.
  1.1191 + */
  1.1192 +static const struct mach_header *image_for_address(const void *address)
  1.1193 +{
  1.1194 +	unsigned long i;
  1.1195 +	unsigned long j;
  1.1196 +	unsigned long count = _dyld_image_count();
  1.1197 +	const struct mach_header *mh = 0;
  1.1198 +	struct load_command *lc = 0;
  1.1199 +	unsigned long addr = 0;
  1.1200 +	for (i = 0; i < count; i++)
  1.1201 +	{
  1.1202 +		addr = (unsigned long)address - _dyld_get_image_vmaddr_slide(i);
  1.1203 +		mh = _dyld_get_image_header(i);
  1.1204 +		if (mh)
  1.1205 +		{
  1.1206 +			lc = (struct load_command *)((char *)mh + sizeof(struct mach_header));
  1.1207 +			for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize))
  1.1208 +			{
  1.1209 +				if (LC_SEGMENT == lc->cmd &&
  1.1210 +					addr >= ((struct segment_command *)lc)->vmaddr &&
  1.1211 +					addr <
  1.1212 +					((struct segment_command *)lc)->vmaddr + ((struct segment_command *)lc)->vmsize)
  1.1213 +				{
  1.1214 +					goto image_found;
  1.1215 +				}
  1.1216 +			}
  1.1217 +		}
  1.1218 +		mh = 0;
  1.1219 +	}
  1.1220 +  image_found:
  1.1221 +	return mh;
  1.1222 +}
  1.1223 +
  1.1224 +#if 0 /* unused */
  1.1225 +static int SDL_OSX_dladdr(const void * dl_restrict p, SDL_OSX_Dl_info * dl_restrict info)
  1.1226 +{
  1.1227 +/*
  1.1228 +	FIXME: USe the routine image_for_address.
  1.1229 +*/
  1.1230 +	unsigned long i;
  1.1231 +	unsigned long j;
  1.1232 +	unsigned long count = _dyld_image_count();
  1.1233 +	struct mach_header *mh = 0;
  1.1234 +	struct load_command *lc = 0;
  1.1235 +	unsigned long addr = NULL;
  1.1236 +	unsigned long table_off = (unsigned long)0;
  1.1237 +	int found = 0;
  1.1238 +	if (!info)
  1.1239 +		return 0;
  1.1240 +	dolock();
  1.1241 +	resetdlerror();
  1.1242 +	info->dli_fname = 0;
  1.1243 +	info->dli_fbase = 0;
  1.1244 +	info->dli_sname = 0;
  1.1245 +	info->dli_saddr = 0;
  1.1246 +/* Some of this was swiped from code posted by Douglas Davidson <ddavidso AT apple DOT com>
  1.1247 + * to darwin-development AT lists DOT apple DOT com and slightly modified
  1.1248 + */
  1.1249 +	for (i = 0; i < count; i++)
  1.1250 +	{
  1.1251 +		addr = (unsigned long)p - _dyld_get_image_vmaddr_slide(i);
  1.1252 +		mh = _dyld_get_image_header(i);
  1.1253 +		if (mh)
  1.1254 +		{
  1.1255 +			lc = (struct load_command *)((char *)mh + sizeof(struct mach_header));
  1.1256 +			for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize))
  1.1257 +			{
  1.1258 +				if (LC_SEGMENT == lc->cmd &&
  1.1259 +					addr >= ((struct segment_command *)lc)->vmaddr &&
  1.1260 +					addr <
  1.1261 +					((struct segment_command *)lc)->vmaddr + ((struct segment_command *)lc)->vmsize)
  1.1262 +				{
  1.1263 +					info->dli_fname = _dyld_get_image_name(i);
  1.1264 +					info->dli_fbase = (void *)mh;
  1.1265 +					found = 1;
  1.1266 +					break;
  1.1267 +				}
  1.1268 +			}
  1.1269 +			if (found)
  1.1270 +				break;
  1.1271 +		}
  1.1272 +	}
  1.1273 +	if (!found)
  1.1274 +	{
  1.1275 +		dounlock();
  1.1276 +		return 0;
  1.1277 +	}
  1.1278 +	lc = (struct load_command *)((char *)mh + sizeof(struct mach_header));
  1.1279 +	for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize))
  1.1280 +	{
  1.1281 +		if (LC_SEGMENT == lc->cmd)
  1.1282 +		{
  1.1283 +			if (!SDL_strcmp(((struct segment_command *)lc)->segname, "__LINKEDIT"))
  1.1284 +				break;
  1.1285 +		}
  1.1286 +	}
  1.1287 +	table_off =
  1.1288 +		((unsigned long)((struct segment_command *)lc)->vmaddr) -
  1.1289 +		((unsigned long)((struct segment_command *)lc)->fileoff) + _dyld_get_image_vmaddr_slide(i);
  1.1290 +	debug("table off %x", table_off);
  1.1291 +
  1.1292 +	lc = (struct load_command *)((char *)mh + sizeof(struct mach_header));
  1.1293 +	for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize))
  1.1294 +	{
  1.1295 +		if (LC_SYMTAB == lc->cmd)
  1.1296 +		{
  1.1297 +
  1.1298 +			struct nlist *symtable = (struct nlist *)(((struct symtab_command *)lc)->symoff + table_off);
  1.1299 +			unsigned long numsyms = ((struct symtab_command *)lc)->nsyms;
  1.1300 +			struct nlist *nearest = NULL;
  1.1301 +			unsigned long diff = 0xffffffff;
  1.1302 +			unsigned long strtable = (unsigned long)(((struct symtab_command *)lc)->stroff + table_off);
  1.1303 +			debug("symtable %x", symtable);
  1.1304 +			for (i = 0; i < numsyms; i++)
  1.1305 +			{
  1.1306 +				/* Ignore the following kinds of Symbols */
  1.1307 +				if ((!symtable->n_value)	/* Undefined */
  1.1308 +					|| (symtable->n_type >= N_PEXT)	/* Debug symbol */
  1.1309 +					|| (!(symtable->n_type & N_EXT))	/* Local Symbol */
  1.1310 +					)
  1.1311 +				{
  1.1312 +					symtable++;
  1.1313 +					continue;
  1.1314 +				}
  1.1315 +				if ((addr >= symtable->n_value) && (diff >= (symtable->n_value - addr)))
  1.1316 +				{
  1.1317 +					diff = (unsigned long)symtable->n_value - addr;
  1.1318 +					nearest = symtable;
  1.1319 +				}
  1.1320 +				symtable++;
  1.1321 +			}
  1.1322 +			if (nearest)
  1.1323 +			{
  1.1324 +				info->dli_saddr = nearest->n_value + ((void *)p - addr);
  1.1325 +				info->dli_sname = (char *)(strtable + nearest->n_un.n_strx);
  1.1326 +			}
  1.1327 +		}
  1.1328 +	}
  1.1329 +	dounlock();
  1.1330 +	return 1;
  1.1331 +}
  1.1332 +#endif
  1.1333 +
  1.1334 +/*
  1.1335 + * Implement the dlfunc() interface, which behaves exactly the same as
  1.1336 + * dlsym() except that it returns a function pointer instead of a data
  1.1337 + * pointer.  This can be used by applications to avoid compiler warnings
  1.1338 + * about undefined behavior, and is intended as prior art for future
  1.1339 + * POSIX standardization.  This function requires that all pointer types
  1.1340 + * have the same representation, which is true on all platforms FreeBSD
  1.1341 + * runs on, but is not guaranteed by the C standard.
  1.1342 + */
  1.1343 +#if 0 
  1.1344 +static dlfunc_t SDL_OSX_dlfunc(void * dl_restrict handle, const char * dl_restrict symbol)
  1.1345 +{
  1.1346 +	union
  1.1347 +	{
  1.1348 +		void *d;
  1.1349 +		dlfunc_t f;
  1.1350 +	} rv;
  1.1351 +	int sym_len = SDL_strlen(symbol);
  1.1352 +	char *malloc_sym = NULL;
  1.1353 +	dolock();
  1.1354 +	malloc_sym = SDL_malloc(sym_len + 2);
  1.1355 +	if (malloc_sym)
  1.1356 +	{
  1.1357 +		SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol);
  1.1358 +		rv.d = dlsymIntern(handle, malloc_sym, 1);
  1.1359 +		SDL_free(malloc_sym);
  1.1360 +	}
  1.1361 +	else
  1.1362 +	{
  1.1363 +		error("Unable to allocate memory");
  1.1364 +		goto dlfuncerror;
  1.1365 +	}
  1.1366 +	dounlock();
  1.1367 +	return rv.f;
  1.1368 +  dlfuncerror:
  1.1369 +	dounlock();
  1.1370 +	return NULL;
  1.1371 +}
  1.1372 +#endif
  1.1373 +
  1.1374 +
  1.1375 +
  1.1376 +/* dlcompat ends, here's the SDL interface...  --ryan.  */
  1.1377 +
  1.1378 +
  1.1379 +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1.1380 +/* System dependent library loading routines                           */
  1.1381 +
  1.1382 +#include "SDL_loadso.h"
  1.1383 +
  1.1384 +void *SDL_LoadObject(const char *sofile)
  1.1385 +{
  1.1386 +	void *handle = SDL_OSX_dlopen(sofile, RTLD_NOW);
  1.1387 +	const char *loaderror = SDL_OSX_dlerror();
  1.1388 +	if ( handle == NULL ) {
  1.1389 +		SDL_SetError("Failed loading %s: %s", sofile, loaderror);
  1.1390 +	}
  1.1391 +	return(handle);
  1.1392 +}
  1.1393 +
  1.1394 +void *SDL_LoadFunction(void *handle, const char *name)
  1.1395 +{
  1.1396 +	void *symbol = SDL_OSX_dlsym(handle, name);
  1.1397 +	if ( symbol == NULL ) {
  1.1398 +		SDL_SetError("Failed loading %s: %s", name, SDL_OSX_dlerror());
  1.1399 +	}
  1.1400 +	return(symbol);
  1.1401 +}
  1.1402 +
  1.1403 +void SDL_UnloadObject(void *handle)
  1.1404 +{
  1.1405 +	if ( handle != NULL ) {
  1.1406 +		SDL_OSX_dlclose(handle);
  1.1407 +	}
  1.1408 +}
  1.1409 +
  1.1410 +#endif /* SDL_LOADSO_DLCOMPAT */
     2.1 --- a/src/loadso/macosx/SDL_sysloadso.c	Wed May 10 06:07:47 2006 +0000
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,1407 +0,0 @@
     2.4 -/*
     2.5 -    SDL - Simple DirectMedia Layer
     2.6 -    Copyright (C) 1997-2006 Sam Lantinga
     2.7 -
     2.8 -    This library is free software; you can redistribute it and/or
     2.9 -    modify it under the terms of the GNU Lesser General Public
    2.10 -    License as published by the Free Software Foundation; either
    2.11 -    version 2.1 of the License, or (at your option) any later version.
    2.12 -
    2.13 -    This library is distributed in the hope that it will be useful,
    2.14 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.15 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    2.16 -    Lesser General Public License for more details.
    2.17 -
    2.18 -    You should have received a copy of the GNU Lesser General Public
    2.19 -    License along with this library; if not, write to the Free Software
    2.20 -    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    2.21 -
    2.22 -    Sam Lantinga
    2.23 -    slouken@libsdl.org
    2.24 -*/
    2.25 -#include "SDL_config.h"
    2.26 -
    2.27 -#ifdef SDL_LOADSO_DLCOMPAT
    2.28 -
    2.29 -/* Please note that dlcompat apparently ships in current Mac OS X versions
    2.30 - *  as a system library that provides compatibility with the Unix "dlopen"
    2.31 - *  interface. In order to allow SDL to work on older OS X releases and also
    2.32 - *  not conflict with the system lib on newer versions, we include dlcompat
    2.33 - *  in SDL and change the symbols to prevent symbol clash with any existing
    2.34 - *  system libraries.  --ryan.
    2.35 - */
    2.36 -
    2.37 -/* here is the dlcompat license: */
    2.38 -
    2.39 -/*
    2.40 -Copyright (c) 2002 Jorge Acereda  <jacereda@users.sourceforge.net> &
    2.41 -                   Peter O'Gorman <ogorman@users.sourceforge.net>
    2.42 -                   
    2.43 -Portions may be copyright others, see the AUTHORS file included with this
    2.44 -distribution.
    2.45 -
    2.46 -Maintained by Peter O'Gorman <ogorman@users.sourceforge.net>
    2.47 -
    2.48 -Bug Reports and other queries should go to <ogorman@users.sourceforge.net>
    2.49 -
    2.50 -Permission is hereby granted, free of charge, to any person obtaining
    2.51 -a copy of this software and associated documentation files (the
    2.52 -"Software"), to deal in the Software without restriction, including
    2.53 -without limitation the rights to use, copy, modify, merge, publish,
    2.54 -distribute, sublicense, and/or sell copies of the Software, and to
    2.55 -permit persons to whom the Software is furnished to do so, subject to
    2.56 -the following conditions:
    2.57 -
    2.58 -The above copyright notice and this permission notice shall be
    2.59 -included in all copies or substantial portions of the Software.
    2.60 -
    2.61 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    2.62 -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    2.63 -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    2.64 -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    2.65 -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    2.66 -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    2.67 -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    2.68 -*/
    2.69 -
    2.70 -#include <pthread.h>
    2.71 -#include <sys/types.h>
    2.72 -#include <sys/stat.h>
    2.73 -#include <stdarg.h>
    2.74 -#include <limits.h>
    2.75 -#include <mach-o/dyld.h>
    2.76 -#include <mach-o/nlist.h>
    2.77 -#include <mach-o/getsect.h>
    2.78 -
    2.79 -#include "SDL_stdinc.h"
    2.80 -
    2.81 -/* Just playing to see if it would compile with the freebsd headers, it does,
    2.82 - * but because of the different values for RTLD_LOCAL etc, it would break binary
    2.83 - * compat... oh well
    2.84 - */
    2.85 -#ifndef __BSD_VISIBLE
    2.86 -#define __BSD_VISIBLE 1
    2.87 -#endif
    2.88 -
    2.89 -/*include "dlfcn.h"*/
    2.90 -#ifdef __cplusplus
    2.91 -extern "C" {
    2.92 -#endif
    2.93 -
    2.94 -#if defined (__GNUC__) && __GNUC__ > 3
    2.95 -#define dl_restrict __restrict
    2.96 -#else
    2.97 -#define dl_restrict
    2.98 -#endif
    2.99 -
   2.100 -#if 0
   2.101 -#ifndef _POSIX_SOURCE
   2.102 -/*
   2.103 - * Structure filled in by dladdr().
   2.104 - */
   2.105 -typedef struct SDL_OSX_dl_info {
   2.106 -        const char      *dli_fname;     /* Pathname of shared object */
   2.107 -        void            *dli_fbase;     /* Base address of shared object */
   2.108 -        const char      *dli_sname;     /* Name of nearest symbol */
   2.109 -        void            *dli_saddr;     /* Address of nearest symbol */
   2.110 -} SDL_OSX_Dl_info;
   2.111 -
   2.112 -static int SDL_OSX_dladdr(const void * dl_restrict, SDL_OSX_Dl_info * dl_restrict);
   2.113 -#endif /* ! _POSIX_SOURCE */
   2.114 -#endif /* 0 */
   2.115 -
   2.116 -static int SDL_OSX_dlclose(void * handle);
   2.117 -static const char * SDL_OSX_dlerror(void);
   2.118 -static void * SDL_OSX_dlopen(const char *path, int mode);
   2.119 -static void * SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol);
   2.120 -
   2.121 -#define RTLD_LAZY	0x1
   2.122 -#define RTLD_NOW	0x2
   2.123 -#define RTLD_LOCAL	0x4
   2.124 -#define RTLD_GLOBAL	0x8
   2.125 -
   2.126 -#ifndef _POSIX_SOURCE
   2.127 -#define RTLD_NOLOAD	0x10
   2.128 -#define RTLD_NODELETE	0x80
   2.129 -
   2.130 -/*
   2.131 - * Special handle arguments for SDL_OSX_dlsym().
   2.132 - */
   2.133 -#define	RTLD_NEXT		((void *) -1)	/* Search subsequent objects. */
   2.134 -#define	RTLD_DEFAULT	((void *) -2)	/* Use default search algorithm. */
   2.135 -#endif /* ! _POSIX_SOURCE */
   2.136 -
   2.137 -#ifdef __cplusplus
   2.138 -}
   2.139 -#endif
   2.140 -
   2.141 -#ifndef dl_restrict
   2.142 -#define dl_restrict __restrict
   2.143 -#endif
   2.144 -/* This is not available on 10.1 */
   2.145 -#ifndef LC_LOAD_WEAK_DYLIB
   2.146 -#define	LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
   2.147 -#endif
   2.148 -
   2.149 -/* With this stuff here, this thing may actually compile/run on 10.0 systems
   2.150 - * Not that I have a 10.0 system to test it on anylonger
   2.151 - */
   2.152 -#ifndef LC_REQ_DYLD
   2.153 -#define LC_REQ_DYLD 0x80000000
   2.154 -#endif
   2.155 -#ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
   2.156 -#define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4
   2.157 -#endif
   2.158 -#ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR
   2.159 -#define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
   2.160 -#endif
   2.161 -#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
   2.162 -#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0
   2.163 -#endif
   2.164 -#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
   2.165 -#define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
   2.166 -#endif
   2.167 -/* These symbols will be looked for in dyld */
   2.168 -static const struct mach_header *(*dyld_NSAddImage) (const char *, unsigned long) = 0;
   2.169 -static int (*dyld_NSIsSymbolNameDefinedInImage) (const struct mach_header *, const char *) = 0;
   2.170 -static NSSymbol(*dyld_NSLookupSymbolInImage)
   2.171 -	(const struct mach_header *, const char *, unsigned long) = 0;
   2.172 -
   2.173 -/* Define this to make dlcompat reuse data block. This way in theory we save
   2.174 - * a little bit of overhead. However we then couldn't correctly catch excess
   2.175 - * calls to SDL_OSX_dlclose(). Hence we don't use this feature
   2.176 - */
   2.177 -#undef REUSE_STATUS
   2.178 -
   2.179 -/* Size of the internal error message buffer (used by dlerror()) */
   2.180 -#define ERR_STR_LEN			251
   2.181 -
   2.182 -/* Maximum number of search paths supported by getSearchPath */
   2.183 -#define MAX_SEARCH_PATHS	32
   2.184 -
   2.185 -
   2.186 -#define MAGIC_DYLIB_OFI ((NSObjectFileImage) 'DYOF')
   2.187 -#define MAGIC_DYLIB_MOD ((NSModule) 'DYMO')
   2.188 -
   2.189 -/* internal flags */
   2.190 -#define DL_IN_LIST 0x01
   2.191 -
   2.192 -/* our mutex */
   2.193 -static pthread_mutex_t dlcompat_mutex;
   2.194 -/* Our thread specific storage
   2.195 - */
   2.196 -static pthread_key_t dlerror_key;
   2.197 -
   2.198 -struct dlthread
   2.199 -{
   2.200 -	int lockcnt;
   2.201 -	unsigned char errset;
   2.202 -	char errstr[ERR_STR_LEN];
   2.203 -};
   2.204 -
   2.205 -/* This is our central data structure. Whenever a module is loaded via
   2.206 - * SDL_OSX_dlopen(), we create such a struct.
   2.207 - */
   2.208 -struct dlstatus
   2.209 -{
   2.210 -	struct dlstatus *next;		/* pointer to next element in the linked list */
   2.211 -	NSModule module;
   2.212 -	const struct mach_header *lib;
   2.213 -	int refs;					/* reference count */
   2.214 -	int mode;					/* mode in which this module was loaded */
   2.215 -	dev_t device;
   2.216 -	ino_t inode;
   2.217 -	int flags;					/* Any internal flags we may need */
   2.218 -};
   2.219 -
   2.220 -/* Head node of the dlstatus list */
   2.221 -static struct dlstatus mainStatus = { 0, MAGIC_DYLIB_MOD, NULL, -1, RTLD_GLOBAL, 0, 0, 0 };
   2.222 -static struct dlstatus *stqueue = &mainStatus;
   2.223 -
   2.224 -
   2.225 -/* Storage for the last error message (used by dlerror()) */
   2.226 -/* static char err_str[ERR_STR_LEN]; */
   2.227 -/* static int err_filled = 0; */
   2.228 -
   2.229 -/* Prototypes to internal functions */
   2.230 -static void debug(const char *fmt, ...);
   2.231 -static void error(const char *str, ...);
   2.232 -static const char *safegetenv(const char *s);
   2.233 -static const char *searchList(void);
   2.234 -static const char *getSearchPath(int i);
   2.235 -static const char *getFullPath(int i, const char *file);
   2.236 -static const struct stat *findFile(const char *file, const char **fullPath);
   2.237 -static int isValidStatus(struct dlstatus *status);
   2.238 -static inline int isFlagSet(int mode, int flag);
   2.239 -static struct dlstatus *lookupStatus(const struct stat *sbuf);
   2.240 -static void insertStatus(struct dlstatus *dls, const struct stat *sbuf);
   2.241 -static int promoteLocalToGlobal(struct dlstatus *dls);
   2.242 -static void *reference(struct dlstatus *dls, int mode);
   2.243 -static void *dlsymIntern(struct dlstatus *dls, const char *symbol, int canSetError);
   2.244 -static struct dlstatus *allocStatus(void);
   2.245 -static struct dlstatus *loadModule(const char *path, const struct stat *sbuf, int mode);
   2.246 -static NSSymbol search_linked_libs(const struct mach_header *mh, const char *symbol);
   2.247 -static const char *get_lib_name(const struct mach_header *mh);
   2.248 -static const struct mach_header *get_mach_header_from_NSModule(NSModule mod);
   2.249 -static void dlcompat_init_func(void);
   2.250 -static inline void dlcompat_init_check(void);
   2.251 -static inline void dolock(void);
   2.252 -static inline void dounlock(void);
   2.253 -static void dlerrorfree(void *data);
   2.254 -static void resetdlerror(void);
   2.255 -static const struct mach_header *my_find_image(const char *name);
   2.256 -static const struct mach_header *image_for_address(const void *address);
   2.257 -static inline char *dyld_error_str(void);
   2.258 -
   2.259 -#if FINK_BUILD
   2.260 -/* Two Global Functions */
   2.261 -static void *dlsym_prepend_underscore(void *handle, const char *symbol);
   2.262 -static void *dlsym_auto_underscore(void *handle, const char *symbol);
   2.263 -
   2.264 -/* And their _intern counterparts */
   2.265 -static void *dlsym_prepend_underscore_intern(void *handle, const char *symbol);
   2.266 -static void *dlsym_auto_underscore_intern(void *handle, const char *symbol);
   2.267 -#endif
   2.268 -
   2.269 -/* Functions */
   2.270 -
   2.271 -static void debug(const char *fmt, ...)
   2.272 -{
   2.273 -#if DEBUG > 1
   2.274 -	va_list arg;
   2.275 -	va_start(arg, fmt);
   2.276 -	fprintf(stderr, "DLDEBUG: ");
   2.277 -	vfprintf(stderr, fmt, arg);
   2.278 -	fprintf(stderr, "\n");
   2.279 -	fflush(stderr);
   2.280 -	va_end(arg);
   2.281 -#endif
   2.282 -}
   2.283 -
   2.284 -static void error(const char *str, ...)
   2.285 -{
   2.286 -	va_list arg;
   2.287 -	struct dlthread  *tss;
   2.288 -	char * err_str;
   2.289 -	va_start(arg, str);
   2.290 -	tss = pthread_getspecific(dlerror_key);
   2.291 -	err_str = tss->errstr;
   2.292 -	SDL_strlcpy(err_str, "dlcompat: ", ERR_STR_LEN);
   2.293 -	vsnprintf(err_str + 10, ERR_STR_LEN - 10, str, arg);
   2.294 -	va_end(arg);
   2.295 -	debug("ERROR: %s\n", err_str);
   2.296 -	tss->errset = 1;
   2.297 -}
   2.298 -
   2.299 -static void warning(const char *str)
   2.300 -{
   2.301 -#if DEBUG > 0
   2.302 -	fprintf(stderr, "WARNING: dlcompat: %s\n", str);
   2.303 -#endif
   2.304 -}
   2.305 -
   2.306 -static const char *safegetenv(const char *s)
   2.307 -{
   2.308 -	const char *ss = SDL_getenv(s);
   2.309 -	return ss ? ss : "";
   2.310 -}
   2.311 -
   2.312 -/* because this is only used for debugging and error reporting functions, we
   2.313 - * don't really care about how elegant it is... it could use the load
   2.314 - * commands to find the install name of the library, but...
   2.315 - */
   2.316 -static const char *get_lib_name(const struct mach_header *mh)
   2.317 -{
   2.318 -	unsigned long count = _dyld_image_count();
   2.319 -	unsigned long i;
   2.320 -	const char *val = NULL;
   2.321 -	if (mh)
   2.322 -	{
   2.323 -		for (i = 0; i < count; i++)
   2.324 -		{
   2.325 -			if (mh == _dyld_get_image_header(i))
   2.326 -			{
   2.327 -				val = _dyld_get_image_name(i);
   2.328 -				break;
   2.329 -			}
   2.330 -		}
   2.331 -	}
   2.332 -	return val;
   2.333 -}
   2.334 -
   2.335 -/* Returns the mach_header for the module bu going through all the loaded images
   2.336 - * and finding the one with the same name as the module. There really ought to be
   2.337 - * an api for doing this, would be faster, but there isn't one right now
   2.338 - */
   2.339 -static const struct mach_header *get_mach_header_from_NSModule(NSModule mod)
   2.340 -{
   2.341 -	const char *mod_name = NSNameOfModule(mod);
   2.342 -	const struct mach_header *mh = NULL;
   2.343 -	unsigned long count = _dyld_image_count();
   2.344 -	unsigned long i;
   2.345 -	debug("Module name: %s", mod_name);
   2.346 -	for (i = 0; i < count; i++)
   2.347 -	{
   2.348 -		if (!SDL_strcmp(mod_name, _dyld_get_image_name(i)))
   2.349 -		{
   2.350 -			mh = _dyld_get_image_header(i);
   2.351 -			break;
   2.352 -		}
   2.353 -	}
   2.354 -	return mh;
   2.355 -}
   2.356 -
   2.357 -
   2.358 -/* Compute and return a list of all directories that we should search when
   2.359 - * trying to locate a module. We first look at the values of LD_LIBRARY_PATH
   2.360 - * and DYLD_LIBRARY_PATH, and then finally fall back to looking into
   2.361 - * /usr/lib and /lib. Since both of the environments variables can contain a
   2.362 - * list of colon seperated paths, we simply concat them and the two other paths
   2.363 - * into one big string, which we then can easily parse.
   2.364 - * Splitting this string into the actual path list is done by getSearchPath()
   2.365 - */
   2.366 -static const char *searchList()
   2.367 -{
   2.368 -	size_t buf_size;
   2.369 -	static char *buf=NULL;
   2.370 -	const char *ldlp = safegetenv("LD_LIBRARY_PATH");
   2.371 -	const char *dyldlp = safegetenv("DYLD_LIBRARY_PATH");
   2.372 -	const char *stdpath = SDL_getenv("DYLD_FALLBACK_LIBRARY_PATH");
   2.373 -	if (!stdpath)
   2.374 -		stdpath = "/usr/local/lib:/lib:/usr/lib";
   2.375 -	if (!buf)
   2.376 -	{	
   2.377 -		buf_size = SDL_strlen(ldlp) + SDL_strlen(dyldlp) + SDL_strlen(stdpath) + 4;
   2.378 -		buf = SDL_malloc(buf_size);
   2.379 -		SDL_snprintf(buf, buf_size, "%s%s%s%s%s%c", dyldlp, (dyldlp[0] ? ":" : ""), ldlp, (ldlp[0] ? ":" : ""),
   2.380 -				 stdpath, '\0');
   2.381 -	}
   2.382 -	return buf;
   2.383 -}
   2.384 -
   2.385 -/* Returns the ith search path from the list as computed by searchList() */
   2.386 -static const char *getSearchPath(int i)
   2.387 -{
   2.388 -	static const char *list = 0;
   2.389 -	static char **path = (char **)0;
   2.390 -	static int end = 0;
   2.391 -	static int numsize = MAX_SEARCH_PATHS;
   2.392 -	static char **tmp;
   2.393 -	/* So we can call SDL_free() in the "destructor" we use i=-1 to return the alloc'd array */
   2.394 -	if (i == -1)
   2.395 -	{
   2.396 -		return (const char*)path;
   2.397 -	}
   2.398 -	if (!path)
   2.399 -	{
   2.400 -		path = (char **)SDL_calloc(MAX_SEARCH_PATHS, sizeof(char **));
   2.401 -	}
   2.402 -	if (!list && !end)
   2.403 -		list = searchList();
   2.404 -	if (i >= (numsize))
   2.405 -	{
   2.406 -		debug("Increasing size for long PATH");
   2.407 -		tmp = (char **)SDL_calloc((MAX_SEARCH_PATHS + numsize), sizeof(char **));
   2.408 -		if (tmp)
   2.409 -		{
   2.410 -			SDL_memcpy(tmp, path, sizeof(char **) * numsize);
   2.411 -			SDL_free(path);
   2.412 -			path = tmp;
   2.413 -			numsize += MAX_SEARCH_PATHS;
   2.414 -		}
   2.415 -		else
   2.416 -		{
   2.417 -			return 0;
   2.418 -		}
   2.419 -	}
   2.420 -
   2.421 -	while (!path[i] && !end)
   2.422 -	{
   2.423 -		path[i] = strsep((char **)&list, ":");
   2.424 -
   2.425 -		if (path[i][0] == 0)
   2.426 -			path[i] = 0;
   2.427 -		end = (list == 0);
   2.428 -	}
   2.429 -	return path[i];
   2.430 -}
   2.431 -
   2.432 -static const char *getFullPath(int i, const char *file)
   2.433 -{
   2.434 -	static char buf[PATH_MAX];
   2.435 -	const char *path = getSearchPath(i);
   2.436 -	if (path)
   2.437 -	{
   2.438 -		SDL_snprintf(buf, PATH_MAX, "%s/%s", path, file);
   2.439 -	}
   2.440 -	return path ? buf : 0;
   2.441 -}
   2.442 -
   2.443 -/* Given a file name, try to determine the full path for that file. Starts
   2.444 - * its search in the current directory, and then tries all paths in the 
   2.445 - * search list in the order they are specified there.
   2.446 - */
   2.447 -static const struct stat *findFile(const char *file, const char **fullPath)
   2.448 -{
   2.449 -	int i = 0;
   2.450 -	static struct stat sbuf;
   2.451 -	char *fileName;
   2.452 -	debug("finding file %s", file);
   2.453 -	*fullPath = file;
   2.454 -	if (0 == stat(file, &sbuf))
   2.455 -		return &sbuf;
   2.456 -	if (SDL_strchr(file, '/'))
   2.457 -		return 0;				/* If the path had a / we don't look in env var places */
   2.458 -	fileName = NULL;
   2.459 -	if (!fileName)
   2.460 -		fileName = (char *)file;
   2.461 -	while ((*fullPath = getFullPath(i++, fileName)))
   2.462 -	{
   2.463 -		if (0 == stat(*fullPath, &sbuf))
   2.464 -			return &sbuf;
   2.465 -	}
   2.466 -	;
   2.467 -	return 0;
   2.468 -}
   2.469 -
   2.470 -/* Determine whether a given dlstatus is valid or not */
   2.471 -static int isValidStatus(struct dlstatus *status)
   2.472 -{
   2.473 -	/* Walk the list to verify status is contained in it */
   2.474 -	struct dlstatus *dls = stqueue;
   2.475 -	while (dls && status != dls)
   2.476 -		dls = dls->next;
   2.477 -	if (dls == 0)
   2.478 -		error("invalid handle");
   2.479 -	else if ((dls->module == 0) || (dls->refs == 0))
   2.480 -		error("handle to closed library");
   2.481 -	else
   2.482 -		return TRUE;
   2.483 -	return FALSE;
   2.484 -}
   2.485 -
   2.486 -static inline int isFlagSet(int mode, int flag)
   2.487 -{
   2.488 -	return (mode & flag) == flag;
   2.489 -}
   2.490 -
   2.491 -static struct dlstatus *lookupStatus(const struct stat *sbuf)
   2.492 -{
   2.493 -	struct dlstatus *dls = stqueue;
   2.494 -	debug("looking for status");
   2.495 -	while (dls && ( /* isFlagSet(dls->mode, RTLD_UNSHARED) */ 0
   2.496 -				   || sbuf->st_dev != dls->device || sbuf->st_ino != dls->inode))
   2.497 -		dls = dls->next;
   2.498 -	return dls;
   2.499 -}
   2.500 -
   2.501 -static void insertStatus(struct dlstatus *dls, const struct stat *sbuf)
   2.502 -{
   2.503 -	debug("inserting status");
   2.504 -	dls->inode = sbuf->st_ino;
   2.505 -	dls->device = sbuf->st_dev;
   2.506 -	dls->refs = 0;
   2.507 -	dls->mode = 0;
   2.508 -	if ((dls->flags & DL_IN_LIST) == 0)
   2.509 -	{
   2.510 -		dls->next = stqueue;
   2.511 -		stqueue = dls;
   2.512 -		dls->flags |= DL_IN_LIST;
   2.513 -	}
   2.514 -}
   2.515 -
   2.516 -static struct dlstatus *allocStatus()
   2.517 -{
   2.518 -	struct dlstatus *dls;
   2.519 -#ifdef REUSE_STATUS
   2.520 -	dls = stqueue;
   2.521 -	while (dls && dls->module)
   2.522 -		dls = dls->next;
   2.523 -	if (!dls)
   2.524 -#endif
   2.525 -		dls = SDL_calloc(sizeof(*dls),1);
   2.526 -	return dls;
   2.527 -}
   2.528 -
   2.529 -static int promoteLocalToGlobal(struct dlstatus *dls)
   2.530 -{
   2.531 -	static int (*p) (NSModule module) = 0;
   2.532 -	debug("promoting");
   2.533 -	if (!p)
   2.534 -		_dyld_func_lookup("__dyld_NSMakePrivateModulePublic", (void **)&p);
   2.535 -	return (dls->module == MAGIC_DYLIB_MOD) || (p && p(dls->module));
   2.536 -}
   2.537 -
   2.538 -static void *reference(struct dlstatus *dls, int mode)
   2.539 -{
   2.540 -	if (dls)
   2.541 -	{
   2.542 -		if (dls->module == MAGIC_DYLIB_MOD && isFlagSet(mode, RTLD_LOCAL))
   2.543 -		{
   2.544 -			warning("trying to open a .dylib with RTLD_LOCAL");
   2.545 -			error("unable to open a .dylib with RTLD_LOCAL");
   2.546 -			return NULL;
   2.547 -		}
   2.548 -		if (isFlagSet(mode, RTLD_GLOBAL) &&
   2.549 -			!isFlagSet(dls->mode, RTLD_GLOBAL) && !promoteLocalToGlobal(dls))
   2.550 -		{
   2.551 -			error("unable to promote local module to global");
   2.552 -			return NULL;
   2.553 -		}
   2.554 -		dls->mode |= mode;
   2.555 -		dls->refs++;
   2.556 -	}
   2.557 -	else
   2.558 -		debug("reference called with NULL argument");
   2.559 -
   2.560 -	return dls;
   2.561 -}
   2.562 -
   2.563 -static const struct mach_header *my_find_image(const char *name)
   2.564 -{
   2.565 -	const struct mach_header *mh = 0;
   2.566 -	const char *id = NULL;
   2.567 -	int i = _dyld_image_count();
   2.568 -	int j;
   2.569 -	mh = (struct mach_header *)
   2.570 -		dyld_NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED |
   2.571 -						NSADDIMAGE_OPTION_RETURN_ON_ERROR);
   2.572 -	if (!mh)
   2.573 -	{
   2.574 -		for (j = 0; j < i; j++)
   2.575 -		{
   2.576 -			id = _dyld_get_image_name(j);
   2.577 -			if (!SDL_strcmp(id, name))
   2.578 -			{
   2.579 -				mh = _dyld_get_image_header(j);
   2.580 -				break;
   2.581 -			}
   2.582 -		}
   2.583 -	}
   2.584 -	return mh;
   2.585 -}
   2.586 -
   2.587 -/*
   2.588 - * dyld adds libraries by first adding the directly dependant libraries in link order, and
   2.589 - * then adding the dependencies for those libraries, so we should do the same... but we don't
   2.590 - * bother adding the extra dependencies, if the symbols are neither in the loaded image nor
   2.591 - * any of it's direct dependencies, then it probably isn't there.
   2.592 - */
   2.593 -static NSSymbol search_linked_libs(const struct mach_header * mh, const char *symbol)
   2.594 -{
   2.595 -	unsigned int n;
   2.596 -	struct load_command *lc = 0;
   2.597 -	struct mach_header *wh;
   2.598 -	NSSymbol nssym = 0;
   2.599 -	if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage)
   2.600 -	{
   2.601 -		lc = (struct load_command *)((char *)mh + sizeof(struct mach_header));
   2.602 -		for (n = 0; n < mh->ncmds; n++, lc = (struct load_command *)((char *)lc + lc->cmdsize))
   2.603 -		{
   2.604 -			if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd))
   2.605 -			{
   2.606 -				if ((wh = (struct mach_header *)
   2.607 -					 my_find_image((char *)(((struct dylib_command *)lc)->dylib.name.offset +
   2.608 -											(char *)lc))))
   2.609 -				{
   2.610 -					if (dyld_NSIsSymbolNameDefinedInImage(wh, symbol))
   2.611 -					{
   2.612 -						nssym = dyld_NSLookupSymbolInImage(wh,
   2.613 -														   symbol,
   2.614 -														   NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
   2.615 -														   NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
   2.616 -						break;
   2.617 -					}
   2.618 -				}
   2.619 -			}
   2.620 -		}
   2.621 -		if ((!nssym) && NSIsSymbolNameDefined(symbol))
   2.622 -		{
   2.623 -			/* I've never seen this debug message...*/
   2.624 -			debug("Symbol \"%s\" is defined but was not found", symbol);
   2.625 -		}
   2.626 -	}
   2.627 -	return nssym;
   2.628 -}
   2.629 -
   2.630 -/* Up to the caller to SDL_free() returned string */
   2.631 -static inline char *dyld_error_str()
   2.632 -{
   2.633 -	NSLinkEditErrors dylder;
   2.634 -	int dylderno;
   2.635 -	const char *dylderrstr;
   2.636 -	const char *dyldfile;
   2.637 -	char* retStr = NULL;
   2.638 -	NSLinkEditError(&dylder, &dylderno, &dyldfile, &dylderrstr);
   2.639 -	if (dylderrstr && *dylderrstr)
   2.640 -	{
   2.641 -		retStr = SDL_strdup(dylderrstr);
   2.642 -	}
   2.643 -	return retStr;
   2.644 -}
   2.645 -
   2.646 -static void *dlsymIntern(struct dlstatus *dls, const char *symbol, int canSetError)
   2.647 -{
   2.648 -  NSSymbol nssym = 0;
   2.649 -#ifdef __GCC__  
   2.650 -	void *caller = __builtin_return_address(1);	/* Be *very* careful about inlining */
   2.651 -#else
   2.652 -	void *caller = NULL;
   2.653 -#endif
   2.654 -	const struct mach_header *caller_mh = 0;
   2.655 -	char *savedErrorStr = NULL;
   2.656 -	resetdlerror();
   2.657 -#ifndef RTLD_SELF
   2.658 -#define	RTLD_SELF		((void *) -3)
   2.659 -#endif
   2.660 -	if (NULL == dls)
   2.661 -		dls = RTLD_SELF;
   2.662 -	if ((RTLD_NEXT == dls) || (RTLD_SELF == dls))
   2.663 -	{
   2.664 -		if (dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage && caller)
   2.665 -		  {
   2.666 -			caller_mh = image_for_address(caller);
   2.667 -			if (RTLD_SELF == dls)
   2.668 -			{
   2.669 -				/* FIXME: We should be using the NSModule api, if SELF is an MH_BUNDLE
   2.670 -				 * But it appears to work anyway, and looking at the code in dyld_libfuncs.c
   2.671 -				 * this is acceptable.
   2.672 -				 */
   2.673 -				if (dyld_NSIsSymbolNameDefinedInImage(caller_mh, symbol))
   2.674 -				{
   2.675 -					nssym = dyld_NSLookupSymbolInImage(caller_mh,
   2.676 -													   symbol,
   2.677 -													   NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
   2.678 -													   NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
   2.679 -				}
   2.680 -			}
   2.681 -			if (!nssym)
   2.682 -			{
   2.683 -				if (RTLD_SELF == dls)
   2.684 -					savedErrorStr = dyld_error_str();
   2.685 -				nssym = search_linked_libs(caller_mh, symbol);
   2.686 -			}
   2.687 -		}
   2.688 -		else
   2.689 -		{
   2.690 -			if (canSetError)
   2.691 -				error("RTLD_SELF and RTLD_NEXT are not supported");
   2.692 -			return NULL;
   2.693 -		}
   2.694 -	}
   2.695 -	if (!nssym)
   2.696 -	{
   2.697 -
   2.698 -		if (RTLD_DEFAULT == dls)
   2.699 -		{
   2.700 -			dls = &mainStatus;
   2.701 -		}
   2.702 -		if (!isValidStatus(dls))
   2.703 -			return NULL;
   2.704 -
   2.705 -		if (dls->module != MAGIC_DYLIB_MOD)
   2.706 -		{
   2.707 -			nssym = NSLookupSymbolInModule(dls->module, symbol);
   2.708 -			if (!nssym && NSIsSymbolNameDefined(symbol))
   2.709 -			{
   2.710 -				debug("Searching dependencies");
   2.711 -				savedErrorStr = dyld_error_str();
   2.712 -				nssym = search_linked_libs(get_mach_header_from_NSModule(dls->module), symbol);
   2.713 -			}
   2.714 -		}
   2.715 -		else if (dls->lib && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage)
   2.716 -		{
   2.717 -			if (dyld_NSIsSymbolNameDefinedInImage(dls->lib, symbol))
   2.718 -			{
   2.719 -				nssym = dyld_NSLookupSymbolInImage(dls->lib,
   2.720 -												   symbol,
   2.721 -												   NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
   2.722 -												   NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
   2.723 -			}
   2.724 -			else if (NSIsSymbolNameDefined(symbol))
   2.725 -			{
   2.726 -				debug("Searching dependencies");
   2.727 -				savedErrorStr = dyld_error_str();
   2.728 -				nssym = search_linked_libs(dls->lib, symbol);
   2.729 -			}
   2.730 -		}
   2.731 -		else if (dls->module == MAGIC_DYLIB_MOD)
   2.732 -		{
   2.733 -			/* Global context, use NSLookupAndBindSymbol */
   2.734 -			if (NSIsSymbolNameDefined(symbol))
   2.735 -			{
   2.736 -				/* There doesn't seem to be a return on error option for this call???
   2.737 -				   this is potentially broken, if binding fails, it will improperly
   2.738 -				   exit the application. */
   2.739 -				nssym = NSLookupAndBindSymbol(symbol);
   2.740 -			}
   2.741 -			else
   2.742 -			{
   2.743 -				if (savedErrorStr)
   2.744 -					SDL_free(savedErrorStr);			
   2.745 -				savedErrorStr = SDL_malloc(256);
   2.746 -				SDL_snprintf(savedErrorStr, 256, "Symbol \"%s\" not in global context",symbol);	
   2.747 -			}
   2.748 -		}
   2.749 -	}
   2.750 -	/* Error reporting */
   2.751 -	if (!nssym)
   2.752 -	{
   2.753 -		if (!savedErrorStr || !SDL_strlen(savedErrorStr))
   2.754 -		{
   2.755 -			if (savedErrorStr)
   2.756 -				SDL_free(savedErrorStr);
   2.757 -			savedErrorStr = SDL_malloc(256);
   2.758 -			SDL_snprintf(savedErrorStr, 256,"Symbol \"%s\" not found",symbol);
   2.759 -		}
   2.760 -		if (canSetError)
   2.761 -		{
   2.762 -			error(savedErrorStr);
   2.763 -		}
   2.764 -		else
   2.765 -		{
   2.766 -			debug(savedErrorStr);
   2.767 -		}
   2.768 -		if (savedErrorStr)
   2.769 -			SDL_free(savedErrorStr);
   2.770 -		return NULL;
   2.771 -	}
   2.772 -	return NSAddressOfSymbol(nssym);
   2.773 -}
   2.774 -
   2.775 -static struct dlstatus *loadModule(const char *path, const struct stat *sbuf, int mode)
   2.776 -{
   2.777 -	NSObjectFileImage ofi = 0;
   2.778 -	NSObjectFileImageReturnCode ofirc;
   2.779 -	struct dlstatus *dls;
   2.780 -	NSLinkEditErrors ler;
   2.781 -	int lerno;
   2.782 -	const char *errstr;
   2.783 -	const char *file;
   2.784 -	void (*init) (void);
   2.785 -
   2.786 -	ofirc = NSCreateObjectFileImageFromFile(path, &ofi);
   2.787 -	switch (ofirc)
   2.788 -	{
   2.789 -		case NSObjectFileImageSuccess:
   2.790 -			break;
   2.791 -		case NSObjectFileImageInappropriateFile:
   2.792 -			if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage)
   2.793 -			{	
   2.794 -				if (isFlagSet(mode, RTLD_LOCAL))
   2.795 -				{
   2.796 -					warning("trying to open a .dylib with RTLD_LOCAL");
   2.797 -					error("unable to open this file with RTLD_LOCAL");
   2.798 -					return NULL;
   2.799 -				}
   2.800 -			}
   2.801 -			else
   2.802 -			{
   2.803 -				error("opening this file is unsupported on this system");
   2.804 -				return NULL;
   2.805 -			}
   2.806 -			break;
   2.807 -		case NSObjectFileImageFailure:
   2.808 -			error("object file setup failure");
   2.809 -			return NULL;
   2.810 -		case NSObjectFileImageArch:
   2.811 -			error("no object for this architecture");
   2.812 -			return NULL;
   2.813 -		case NSObjectFileImageFormat:
   2.814 -			error("bad object file format");
   2.815 -			return NULL;
   2.816 -		case NSObjectFileImageAccess:
   2.817 -			error("can't read object file");
   2.818 -			return NULL;
   2.819 -		default:
   2.820 -			error("unknown error from NSCreateObjectFileImageFromFile()");
   2.821 -			return NULL;
   2.822 -	}
   2.823 -	dls = lookupStatus(sbuf);
   2.824 -	if (!dls)
   2.825 -	{
   2.826 -		dls = allocStatus();
   2.827 -	}
   2.828 -	if (!dls)
   2.829 -	{
   2.830 -		error("unable to allocate memory");
   2.831 -		return NULL;
   2.832 -	}
   2.833 -	//	dls->lib = 0;
   2.834 -	if (ofirc == NSObjectFileImageInappropriateFile)
   2.835 -	{
   2.836 -		if ((dls->lib = dyld_NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR)))
   2.837 -		{
   2.838 -			debug("Dynamic lib loaded at %ld", dls->lib);
   2.839 -			ofi = MAGIC_DYLIB_OFI;
   2.840 -			dls->module = MAGIC_DYLIB_MOD;
   2.841 -			ofirc = NSObjectFileImageSuccess;
   2.842 -			/* Although it is possible with a bit of work to modify this so it works and
   2.843 -			   functions with RTLD_NOW, I don't deem it necessary at the moment */
   2.844 -		}
   2.845 -		if (!(dls->module))
   2.846 -		{
   2.847 -			NSLinkEditError(&ler, &lerno, &file, &errstr);
   2.848 -			if (!errstr || (!SDL_strlen(errstr)))
   2.849 -				error("Can't open this file type");
   2.850 -			else
   2.851 -				error(errstr);
   2.852 -			if ((dls->flags & DL_IN_LIST) == 0)
   2.853 -			{
   2.854 -				SDL_free(dls);
   2.855 -			}
   2.856 -			return NULL;
   2.857 -		}
   2.858 -	}
   2.859 -	else
   2.860 -	{
   2.861 -		dls->module = NSLinkModule(ofi, path,
   2.862 -								   NSLINKMODULE_OPTION_RETURN_ON_ERROR |
   2.863 -								   NSLINKMODULE_OPTION_PRIVATE |
   2.864 -								   (isFlagSet(mode, RTLD_NOW) ? NSLINKMODULE_OPTION_BINDNOW : 0));
   2.865 -		NSDestroyObjectFileImage(ofi);
   2.866 -		if (dls->module)
   2.867 -		{
   2.868 -			dls->lib = get_mach_header_from_NSModule(dls->module);
   2.869 -		}
   2.870 -	}
   2.871 -	if (!dls->module)
   2.872 -	{
   2.873 -		NSLinkEditError(&ler, &lerno, &file, &errstr);
   2.874 -		if ((dls->flags & DL_IN_LIST) == 0)
   2.875 -		{
   2.876 -			SDL_free(dls);
   2.877 -		}
   2.878 -		error(errstr);
   2.879 -		return NULL;
   2.880 -	}
   2.881 -
   2.882 -	insertStatus(dls, sbuf);
   2.883 -	dls = reference(dls, mode);
   2.884 -	if ((init = dlsymIntern(dls, "__init", 0)))
   2.885 -	{
   2.886 -		debug("calling _init()");
   2.887 -		init();
   2.888 -	}
   2.889 -	return dls;
   2.890 -}
   2.891 -
   2.892 -inline static void dlcompat_init_check(void)
   2.893 -{
   2.894 -	static pthread_mutex_t l = PTHREAD_MUTEX_INITIALIZER;
   2.895 -	static int init_done = 0;
   2.896 -
   2.897 -	pthread_mutex_lock(&l);
   2.898 -	if (!init_done) {
   2.899 -		dlcompat_init_func();
   2.900 -		init_done = 1;
   2.901 -	}
   2.902 -	pthread_mutex_unlock(&l);
   2.903 -}
   2.904 -
   2.905 -static void dlcompat_init_func(void)
   2.906 -{
   2.907 -        _dyld_func_lookup("__dyld_NSAddImage", (void **)&dyld_NSAddImage);
   2.908 -	_dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",
   2.909 -			  (void **)&dyld_NSIsSymbolNameDefinedInImage);
   2.910 -	_dyld_func_lookup("__dyld_NSLookupSymbolInImage", (void **)&dyld_NSLookupSymbolInImage);
   2.911 -	if (pthread_mutex_init(&dlcompat_mutex, NULL))
   2.912 -	    exit(1);
   2.913 -	if (pthread_key_create(&dlerror_key, &dlerrorfree))
   2.914 -	    exit(1);
   2.915 -}
   2.916 -
   2.917 -static void resetdlerror()
   2.918 -{
   2.919 -	struct dlthread *tss;
   2.920 -	tss = pthread_getspecific(dlerror_key);
   2.921 -	tss->errset = 0;
   2.922 -}
   2.923 -
   2.924 -static void dlerrorfree(void *data)
   2.925 -{
   2.926 -	SDL_free(data);
   2.927 -}
   2.928 -
   2.929 -/* We kind of want a recursive lock here, but meet a little trouble
   2.930 - * because they are not available pre OS X 10.2, so we fake it
   2.931 - * using thread specific storage to keep a lock count
   2.932 - */ 
   2.933 -static inline void dolock(void)
   2.934 -{
   2.935 -	int err = 0;
   2.936 -	struct dlthread *tss;
   2.937 -	dlcompat_init_check();
   2.938 -	tss = pthread_getspecific(dlerror_key);
   2.939 -	if (!tss)
   2.940 -	{
   2.941 -		tss = SDL_malloc(sizeof(struct dlthread));
   2.942 -		tss->lockcnt = 0;
   2.943 -		tss->errset = 0;
   2.944 -		if (pthread_setspecific(dlerror_key, tss))
   2.945 -		{
   2.946 -			fprintf(stderr,"dlcompat: pthread_setspecific failed\n");
   2.947 -			exit(1);
   2.948 -		}
   2.949 -	}
   2.950 -	if (!tss->lockcnt)
   2.951 -		err = pthread_mutex_lock(&dlcompat_mutex);
   2.952 -	tss->lockcnt = tss->lockcnt +1;	
   2.953 -	if (err)
   2.954 -		exit(err);
   2.955 -}
   2.956 -
   2.957 -static inline void dounlock(void)
   2.958 -{
   2.959 -	int err = 0;
   2.960 -	struct dlthread *tss;
   2.961 -	tss = pthread_getspecific(dlerror_key);
   2.962 -	tss->lockcnt = tss->lockcnt -1;
   2.963 -	if (!tss->lockcnt)
   2.964 -		err = pthread_mutex_unlock(&dlcompat_mutex);
   2.965 -	if (err)
   2.966 -		exit(err);
   2.967 -}
   2.968 -
   2.969 -static void *SDL_OSX_dlopen(const char *path, int mode)
   2.970 -{
   2.971 -	const struct stat *sbuf;
   2.972 -	struct dlstatus *dls;
   2.973 -	const char *fullPath;
   2.974 -
   2.975 -	dolock();
   2.976 -	resetdlerror();
   2.977 -	if (!path)
   2.978 -	{
   2.979 -		dls = &mainStatus;
   2.980 -		goto dlopenok;
   2.981 -	}
   2.982 -	if (!(sbuf = findFile(path, &fullPath)))
   2.983 -	{
   2.984 -		error("file \"%s\" not found", path);
   2.985 -		goto dlopenerror;
   2.986 -	}
   2.987 -	/* Now checks that it hasn't been closed already */
   2.988 -	if ((dls = lookupStatus(sbuf)) && (dls->refs > 0))
   2.989 -	{
   2.990 -		/* debug("status found"); */
   2.991 -		dls = reference(dls, mode);
   2.992 -		goto dlopenok;
   2.993 -	}
   2.994 -#ifdef 	RTLD_NOLOAD
   2.995 -	if (isFlagSet(mode, RTLD_NOLOAD))
   2.996 -	{
   2.997 -		error("no existing handle and RTLD_NOLOAD specified");
   2.998 -		goto dlopenerror;
   2.999 -	}
  2.1000 -#endif
  2.1001 -	if (isFlagSet(mode, RTLD_LAZY) && isFlagSet(mode, RTLD_NOW))
  2.1002 -	{
  2.1003 -		error("how can I load something both RTLD_LAZY and RTLD_NOW?");
  2.1004 -		goto dlopenerror;
  2.1005 -	}
  2.1006 -	dls = loadModule(fullPath, sbuf, mode);
  2.1007 -	
  2.1008 -  dlopenok:
  2.1009 -	dounlock();
  2.1010 -	return (void *)dls;
  2.1011 -  dlopenerror:
  2.1012 -	dounlock();
  2.1013 -	return NULL;
  2.1014 -}
  2.1015 -
  2.1016 -#if !FINK_BUILD
  2.1017 -static void *SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol)
  2.1018 -{
  2.1019 -	int sym_len = SDL_strlen(symbol);
  2.1020 -	void *value = NULL;
  2.1021 -	char *malloc_sym = NULL;
  2.1022 -	dolock();
  2.1023 -	malloc_sym = SDL_malloc(sym_len + 2);
  2.1024 -	if (malloc_sym)
  2.1025 -	{
  2.1026 -		SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol);
  2.1027 -		value = dlsymIntern(handle, malloc_sym, 1);
  2.1028 -		SDL_free(malloc_sym);
  2.1029 -	}
  2.1030 -	else
  2.1031 -	{
  2.1032 -		error("Unable to allocate memory");
  2.1033 -		goto dlsymerror;
  2.1034 -	}
  2.1035 -	dounlock();
  2.1036 -	return value;
  2.1037 -  dlsymerror:
  2.1038 -	dounlock();
  2.1039 -	return NULL;
  2.1040 -}
  2.1041 -#endif
  2.1042 -
  2.1043 -#if FINK_BUILD
  2.1044 -
  2.1045 -static void *dlsym_prepend_underscore(void *handle, const char *symbol)
  2.1046 -{
  2.1047 -	void *answer;
  2.1048 -	dolock();
  2.1049 -	answer = dlsym_prepend_underscore_intern(handle, symbol);
  2.1050 -	dounlock();
  2.1051 -	return answer;
  2.1052 -}
  2.1053 -
  2.1054 -static void *dlsym_prepend_underscore_intern(void *handle, const char *symbol)
  2.1055 -{
  2.1056 -/*
  2.1057 - *	A quick and easy way for porting packages which call dlsym(handle,"sym")
  2.1058 - *	If the porter adds -Ddlsym=dlsym_prepend_underscore to the CFLAGS then
  2.1059 - *	this function will be called, and will add the required underscore.
  2.1060 - *	
  2.1061 - *	Note that I haven't figured out yet which should be "standard", prepend
  2.1062 - *	the underscore always, or not at all. These global functions need to go away
  2.1063 - *	for opendarwin.
  2.1064 - */
  2.1065 -	int sym_len = SDL_strlen(symbol);
  2.1066 -	void *value = NULL;
  2.1067 -	char *malloc_sym = NULL;
  2.1068 -	malloc_sym = SDL_malloc(sym_len + 2);
  2.1069 -	if (malloc_sym)
  2.1070 -	{
  2.1071 -		SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol);
  2.1072 -		value = dlsymIntern(handle, malloc_sym, 1);
  2.1073 -		SDL_free(malloc_sym);
  2.1074 -	}
  2.1075 -	else
  2.1076 -	{
  2.1077 -		error("Unable to allocate memory");
  2.1078 -	}
  2.1079 -	return value;
  2.1080 -}
  2.1081 -
  2.1082 -static void *dlsym_auto_underscore(void *handle, const char *symbol)
  2.1083 -{
  2.1084 -	void *answer;
  2.1085 -	dolock();
  2.1086 -	answer = dlsym_auto_underscore_intern(handle, symbol);
  2.1087 -	dounlock();
  2.1088 -	return answer;
  2.1089 -
  2.1090 -}
  2.1091 -static void *dlsym_auto_underscore_intern(void *handle, const char *symbol)
  2.1092 -{
  2.1093 -	struct dlstatus *dls = handle;
  2.1094 -	void *addr = 0;
  2.1095 -	addr = dlsymIntern(dls, symbol, 0);
  2.1096 -	if (!addr)
  2.1097 -		addr = dlsym_prepend_underscore_intern(handle, symbol);
  2.1098 -	return addr;
  2.1099 -}
  2.1100 -
  2.1101 -
  2.1102 -static void *SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol)
  2.1103 -{
  2.1104 -	struct dlstatus *dls = handle;
  2.1105 -	void *addr = 0;
  2.1106 -	dolock();
  2.1107 -	addr = dlsymIntern(dls, symbol, 1);
  2.1108 -	dounlock();
  2.1109 -	return addr;
  2.1110 -}
  2.1111 -#endif
  2.1112 -
  2.1113 -static int SDL_OSX_dlclose(void *handle)
  2.1114 -{
  2.1115 -	struct dlstatus *dls = handle;
  2.1116 -	dolock();
  2.1117 -	resetdlerror();
  2.1118 -	if (!isValidStatus(dls))
  2.1119 -	{
  2.1120 -		goto dlcloseerror;
  2.1121 -	}
  2.1122 -	if (dls->module == MAGIC_DYLIB_MOD)
  2.1123 -	{
  2.1124 -		const char *name;
  2.1125 -		if (!dls->lib)
  2.1126 -		{
  2.1127 -			name = "global context";
  2.1128 -		}
  2.1129 -		else
  2.1130 -		{
  2.1131 -			name = get_lib_name(dls->lib);
  2.1132 -		}
  2.1133 -		warning("trying to close a .dylib!");
  2.1134 -		error("Not closing \"%s\" - dynamic libraries cannot be closed", name);
  2.1135 -		goto dlcloseerror;
  2.1136 -	}
  2.1137 -	if (!dls->module)
  2.1138 -	{
  2.1139 -		error("module already closed");
  2.1140 -		goto dlcloseerror;
  2.1141 -	}
  2.1142 -	
  2.1143 -	if (dls->refs == 1)
  2.1144 -	{
  2.1145 -		unsigned long options = 0;
  2.1146 -		void (*fini) (void);
  2.1147 -		if ((fini = dlsymIntern(dls, "__fini", 0)))
  2.1148 -		{
  2.1149 -			debug("calling _fini()");
  2.1150 -			fini();
  2.1151 -		}
  2.1152 -		options |= NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
  2.1153 -#ifdef RTLD_NODELETE
  2.1154 -		if (isFlagSet(dls->mode, RTLD_NODELETE))
  2.1155 -			options |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
  2.1156 -#endif
  2.1157 -		if (!NSUnLinkModule(dls->module, options))
  2.1158 -		{
  2.1159 -			error("unable to unlink module");
  2.1160 -			goto dlcloseerror;
  2.1161 -		}
  2.1162 -		dls->refs--;
  2.1163 -		dls->module = 0;
  2.1164 -		/* Note: the dlstatus struct dls is neither removed from the list
  2.1165 -		 * nor is the memory it occupies freed. This shouldn't pose a 
  2.1166 -		 * problem in mostly all cases, though.
  2.1167 -		 */
  2.1168 -	}
  2.1169 -	dounlock();
  2.1170 -	return 0;
  2.1171 -  dlcloseerror:
  2.1172 -	dounlock();
  2.1173 -	return 1;
  2.1174 -}
  2.1175 -
  2.1176 -static const char *SDL_OSX_dlerror(void)
  2.1177 -{
  2.1178 -	struct dlthread  *tss;
  2.1179 -	const char * err_str = NULL;
  2.1180 -	dlcompat_init_check();
  2.1181 -	tss = pthread_getspecific(dlerror_key);
  2.1182 -	if (tss != NULL && tss->errset != 0) {
  2.1183 -		tss->errset = 0;	
  2.1184 -		err_str = tss->errstr;
  2.1185 -	}
  2.1186 -	return (err_str);
  2.1187 -}
  2.1188 -
  2.1189 -/* Given an address, return the mach_header for the image containing it
  2.1190 - * or zero if the given address is not contained in any loaded images.
  2.1191 - */
  2.1192 -static const struct mach_header *image_for_address(const void *address)
  2.1193 -{
  2.1194 -	unsigned long i;
  2.1195 -	unsigned long j;
  2.1196 -	unsigned long count = _dyld_image_count();
  2.1197 -	const struct mach_header *mh = 0;
  2.1198 -	struct load_command *lc = 0;
  2.1199 -	unsigned long addr = 0;
  2.1200 -	for (i = 0; i < count; i++)
  2.1201 -	{
  2.1202 -		addr = (unsigned long)address - _dyld_get_image_vmaddr_slide(i);
  2.1203 -		mh = _dyld_get_image_header(i);
  2.1204 -		if (mh)
  2.1205 -		{
  2.1206 -			lc = (struct load_command *)((char *)mh + sizeof(struct mach_header));
  2.1207 -			for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize))
  2.1208 -			{
  2.1209 -				if (LC_SEGMENT == lc->cmd &&
  2.1210 -					addr >= ((struct segment_command *)lc)->vmaddr &&
  2.1211 -					addr <
  2.1212 -					((struct segment_command *)lc)->vmaddr + ((struct segment_command *)lc)->vmsize)
  2.1213 -				{
  2.1214 -					goto image_found;
  2.1215 -				}
  2.1216 -			}
  2.1217 -		}
  2.1218 -		mh = 0;
  2.1219 -	}
  2.1220 -  image_found:
  2.1221 -	return mh;
  2.1222 -}
  2.1223 -
  2.1224 -#if 0 /* unused */
  2.1225 -static int SDL_OSX_dladdr(const void * dl_restrict p, SDL_OSX_Dl_info * dl_restrict info)
  2.1226 -{
  2.1227 -/*
  2.1228 -	FIXME: USe the routine image_for_address.
  2.1229 -*/
  2.1230 -	unsigned long i;
  2.1231 -	unsigned long j;
  2.1232 -	unsigned long count = _dyld_image_count();
  2.1233 -	struct mach_header *mh = 0;
  2.1234 -	struct load_command *lc = 0;
  2.1235 -	unsigned long addr = NULL;
  2.1236 -	unsigned long table_off = (unsigned long)0;
  2.1237 -	int found = 0;
  2.1238 -	if (!info)
  2.1239 -		return 0;
  2.1240 -	dolock();
  2.1241 -	resetdlerror();
  2.1242 -	info->dli_fname = 0;
  2.1243 -	info->dli_fbase = 0;
  2.1244 -	info->dli_sname = 0;
  2.1245 -	info->dli_saddr = 0;
  2.1246 -/* Some of this was swiped from code posted by Douglas Davidson <ddavidso AT apple DOT com>
  2.1247 - * to darwin-development AT lists DOT apple DOT com and slightly modified
  2.1248 - */
  2.1249 -	for (i = 0; i < count; i++)
  2.1250 -	{
  2.1251 -		addr = (unsigned long)p - _dyld_get_image_vmaddr_slide(i);
  2.1252 -		mh = _dyld_get_image_header(i);
  2.1253 -		if (mh)
  2.1254 -		{
  2.1255 -			lc = (struct load_command *)((char *)mh + sizeof(struct mach_header));
  2.1256 -			for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize))
  2.1257 -			{
  2.1258 -				if (LC_SEGMENT == lc->cmd &&
  2.1259 -					addr >= ((struct segment_command *)lc)->vmaddr &&
  2.1260 -					addr <
  2.1261 -					((struct segment_command *)lc)->vmaddr + ((struct segment_command *)lc)->vmsize)
  2.1262 -				{
  2.1263 -					info->dli_fname = _dyld_get_image_name(i);
  2.1264 -					info->dli_fbase = (void *)mh;
  2.1265 -					found = 1;
  2.1266 -					break;
  2.1267 -				}
  2.1268 -			}
  2.1269 -			if (found)
  2.1270 -				break;
  2.1271 -		}
  2.1272 -	}
  2.1273 -	if (!found)
  2.1274 -	{
  2.1275 -		dounlock();
  2.1276 -		return 0;
  2.1277 -	}
  2.1278 -	lc = (struct load_command *)((char *)mh + sizeof(struct mach_header));
  2.1279 -	for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize))
  2.1280 -	{
  2.1281 -		if (LC_SEGMENT == lc->cmd)
  2.1282 -		{
  2.1283 -			if (!SDL_strcmp(((struct segment_command *)lc)->segname, "__LINKEDIT"))
  2.1284 -				break;
  2.1285 -		}
  2.1286 -	}
  2.1287 -	table_off =
  2.1288 -		((unsigned long)((struct segment_command *)lc)->vmaddr) -
  2.1289 -		((unsigned long)((struct segment_command *)lc)->fileoff) + _dyld_get_image_vmaddr_slide(i);
  2.1290 -	debug("table off %x", table_off);
  2.1291 -
  2.1292 -	lc = (struct load_command *)((char *)mh + sizeof(struct mach_header));
  2.1293 -	for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize))
  2.1294 -	{
  2.1295 -		if (LC_SYMTAB == lc->cmd)
  2.1296 -		{
  2.1297 -
  2.1298 -			struct nlist *symtable = (struct nlist *)(((struct symtab_command *)lc)->symoff + table_off);
  2.1299 -			unsigned long numsyms = ((struct symtab_command *)lc)->nsyms;
  2.1300 -			struct nlist *nearest = NULL;
  2.1301 -			unsigned long diff = 0xffffffff;
  2.1302 -			unsigned long strtable = (unsigned long)(((struct symtab_command *)lc)->stroff + table_off);
  2.1303 -			debug("symtable %x", symtable);
  2.1304 -			for (i = 0; i < numsyms; i++)
  2.1305 -			{
  2.1306 -				/* Ignore the following kinds of Symbols */
  2.1307 -				if ((!symtable->n_value)	/* Undefined */
  2.1308 -					|| (symtable->n_type >= N_PEXT)	/* Debug symbol */
  2.1309 -					|| (!(symtable->n_type & N_EXT))	/* Local Symbol */
  2.1310 -					)
  2.1311 -				{
  2.1312 -					symtable++;
  2.1313 -					continue;
  2.1314 -				}
  2.1315 -				if ((addr >= symtable->n_value) && (diff >= (symtable->n_value - addr)))
  2.1316 -				{
  2.1317 -					diff = (unsigned long)symtable->n_value - addr;
  2.1318 -					nearest = symtable;
  2.1319 -				}
  2.1320 -				symtable++;
  2.1321 -			}
  2.1322 -			if (nearest)
  2.1323 -			{
  2.1324 -				info->dli_saddr = nearest->n_value + ((void *)p - addr);
  2.1325 -				info->dli_sname = (char *)(strtable + nearest->n_un.n_strx);
  2.1326 -			}
  2.1327 -		}
  2.1328 -	}
  2.1329 -	dounlock();
  2.1330 -	return 1;
  2.1331 -}
  2.1332 -#endif
  2.1333 -
  2.1334 -/*
  2.1335 - * Implement the dlfunc() interface, which behaves exactly the same as
  2.1336 - * dlsym() except that it returns a function pointer instead of a data
  2.1337 - * pointer.  This can be used by applications to avoid compiler warnings
  2.1338 - * about undefined behavior, and is intended as prior art for future
  2.1339 - * POSIX standardization.  This function requires that all pointer types
  2.1340 - * have the same representation, which is true on all platforms FreeBSD
  2.1341 - * runs on, but is not guaranteed by the C standard.
  2.1342 - */
  2.1343 -#if 0 
  2.1344 -static dlfunc_t SDL_OSX_dlfunc(void * dl_restrict handle, const char * dl_restrict symbol)
  2.1345 -{
  2.1346 -	union
  2.1347 -	{
  2.1348 -		void *d;
  2.1349 -		dlfunc_t f;
  2.1350 -	} rv;
  2.1351 -	int sym_len = SDL_strlen(symbol);
  2.1352 -	char *malloc_sym = NULL;
  2.1353 -	dolock();
  2.1354 -	malloc_sym = SDL_malloc(sym_len + 2);
  2.1355 -	if (malloc_sym)
  2.1356 -	{
  2.1357 -		SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol);
  2.1358 -		rv.d = dlsymIntern(handle, malloc_sym, 1);
  2.1359 -		SDL_free(malloc_sym);
  2.1360 -	}
  2.1361 -	else
  2.1362 -	{
  2.1363 -		error("Unable to allocate memory");
  2.1364 -		goto dlfuncerror;
  2.1365 -	}
  2.1366 -	dounlock();
  2.1367 -	return rv.f;
  2.1368 -  dlfuncerror:
  2.1369 -	dounlock();
  2.1370 -	return NULL;
  2.1371 -}
  2.1372 -#endif
  2.1373 -
  2.1374 -
  2.1375 -
  2.1376 -/* dlcompat ends, here's the SDL interface...  --ryan.  */
  2.1377 -
  2.1378 -
  2.1379 -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  2.1380 -/* System dependent library loading routines                           */
  2.1381 -
  2.1382 -#include "SDL_loadso.h"
  2.1383 -
  2.1384 -void *SDL_LoadObject(const char *sofile)
  2.1385 -{
  2.1386 -	void *handle = SDL_OSX_dlopen(sofile, RTLD_NOW);
  2.1387 -	const char *loaderror = SDL_OSX_dlerror();
  2.1388 -	if ( handle == NULL ) {
  2.1389 -		SDL_SetError("Failed loading %s: %s", sofile, loaderror);
  2.1390 -	}
  2.1391 -	return(handle);
  2.1392 -}
  2.1393 -
  2.1394 -void *SDL_LoadFunction(void *handle, const char *name)
  2.1395 -{
  2.1396 -	void *symbol = SDL_OSX_dlsym(handle, name);
  2.1397 -	if ( symbol == NULL ) {
  2.1398 -		SDL_SetError("Failed loading %s: %s", name, SDL_OSX_dlerror());
  2.1399 -	}
  2.1400 -	return(symbol);
  2.1401 -}
  2.1402 -
  2.1403 -void SDL_UnloadObject(void *handle)
  2.1404 -{
  2.1405 -	if ( handle != NULL ) {
  2.1406 -		SDL_OSX_dlclose(handle);
  2.1407 -	}
  2.1408 -}
  2.1409 -
  2.1410 -#endif /* SDL_LOADSO_DLCOMPAT */