19682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
29682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    SDL - Simple DirectMedia Layer
39682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Copyright (C) 1997-2012 Sam Lantinga
49682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
59682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    This library is free software; you can redistribute it and/or
69682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    modify it under the terms of the GNU Lesser General Public
79682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    License as published by the Free Software Foundation; either
89682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    version 2.1 of the License, or (at your option) any later version.
99682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    This library is distributed in the hope that it will be useful,
119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    but WITHOUT ANY WARRANTY; without even the implied warranty of
129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Lesser General Public License for more details.
149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    You should have received a copy of the GNU Lesser General Public
169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    License along with this library; if not, write to the Free Software
179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    Sam Lantinga
209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall    slouken@libsdl.org
219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_config.h"
239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef SDL_LOADSO_DLCOMPAT
259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Please note that dlcompat apparently ships in current Mac OS X versions
279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *  as a system library that provides compatibility with the Unix "dlopen"
289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *  interface. In order to allow SDL to work on older OS X releases and also
299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *  not conflict with the system lib on newer versions, we include dlcompat
309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *  in SDL and change the symbols to prevent symbol clash with any existing
319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *  system libraries.  --ryan.
329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* here is the dlcompat license: */
359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallCopyright (c) 2002 Jorge Acereda  <jacereda@users.sourceforge.net> &
389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall                   Peter O'Gorman <ogorman@users.sourceforge.net>
399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallPortions may be copyright others, see the AUTHORS file included with this
419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Halldistribution.
429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallMaintained by Peter O'Gorman <ogorman@users.sourceforge.net>
449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallBug Reports and other queries should go to <ogorman@users.sourceforge.net>
469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallPermission is hereby granted, free of charge, to any person obtaining
489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Halla copy of this software and associated documentation files (the
499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall"Software"), to deal in the Software without restriction, including
509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallwithout limitation the rights to use, copy, modify, merge, publish,
519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Halldistribute, sublicense, and/or sell copies of the Software, and to
529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallpermit persons to whom the Software is furnished to do so, subject to
539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallthe following conditions:
549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallThe above copyright notice and this permission notice shall be
569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallincluded in all copies or substantial portions of the Software.
579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse HallWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <pthread.h>
689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <sys/types.h>
699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <sys/stat.h>
709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <stdarg.h>
719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <limits.h>
729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <mach-o/dyld.h>
739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <mach-o/nlist.h>
749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include <mach-o/getsect.h>
759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_stdinc.h"
779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Just playing to see if it would compile with the freebsd headers, it does,
799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * but because of the different values for RTLD_LOCAL etc, it would break binary
809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * compat... oh well
819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef __BSD_VISIBLE
839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define __BSD_VISIBLE 1
849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*include "dlfcn.h"*/
879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef __cplusplus
889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallextern "C" {
899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if defined (__GNUC__) && __GNUC__ > 3
929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define dl_restrict __restrict
939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else
949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define dl_restrict
959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if 0
989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef _POSIX_SOURCE
999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
1009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * Structure filled in by dladdr().
1019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
1029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Halltypedef struct SDL_OSX_dl_info {
1039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        const char      *dli_fname;     /* Pathname of shared object */
1049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        void            *dli_fbase;     /* Base address of shared object */
1059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        const char      *dli_sname;     /* Name of nearest symbol */
1069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        void            *dli_saddr;     /* Address of nearest symbol */
1079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall} SDL_OSX_Dl_info;
1089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int SDL_OSX_dladdr(const void * dl_restrict, SDL_OSX_Dl_info * dl_restrict);
1109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* ! _POSIX_SOURCE */
1119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* 0 */
1129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int SDL_OSX_dlclose(void * handle);
1149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic const char * SDL_OSX_dlerror(void);
1159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void * SDL_OSX_dlopen(const char *path, int mode);
1169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void * SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol);
1179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define RTLD_LAZY	0x1
1199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define RTLD_NOW	0x2
1209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define RTLD_LOCAL	0x4
1219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define RTLD_GLOBAL	0x8
1229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef _POSIX_SOURCE
1249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define RTLD_NOLOAD	0x10
1259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define RTLD_NODELETE	0x80
1269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
1289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * Special handle arguments for SDL_OSX_dlsym().
1299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
1309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define	RTLD_NEXT		((void *) -1)	/* Search subsequent objects. */
1319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define	RTLD_DEFAULT	((void *) -2)	/* Use default search algorithm. */
1329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* ! _POSIX_SOURCE */
1339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef __cplusplus
1359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
1369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
1379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef dl_restrict
1399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define dl_restrict __restrict
1409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
1419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* This is not available on 10.1 */
1429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef LC_LOAD_WEAK_DYLIB
1439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define	LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
1449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
1459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* With this stuff here, this thing may actually compile/run on 10.0 systems
1479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * Not that I have a 10.0 system to test it on anylonger
1489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
1499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef LC_REQ_DYLD
1509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define LC_REQ_DYLD 0x80000000
1519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
1529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
1539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4
1549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
1559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR
1569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
1579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
1589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
1599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0
1609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
1619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
1639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
1649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* These symbols will be looked for in dyld */
1659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic const struct mach_header *(*dyld_NSAddImage) (const char *, unsigned long) = 0;
1669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int (*dyld_NSIsSymbolNameDefinedInImage) (const struct mach_header *, const char *) = 0;
1679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic NSSymbol(*dyld_NSLookupSymbolInImage)
1689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	(const struct mach_header *, const char *, unsigned long) = 0;
1699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Define this to make dlcompat reuse data block. This way in theory we save
1719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * a little bit of overhead. However we then couldn't correctly catch excess
1729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * calls to SDL_OSX_dlclose(). Hence we don't use this feature
1739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
1749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#undef REUSE_STATUS
1759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Size of the internal error message buffer (used by dlerror()) */
1779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define ERR_STR_LEN			251
1789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Maximum number of search paths supported by getSearchPath */
1809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MAX_SEARCH_PATHS	32
1819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MAGIC_DYLIB_OFI ((NSObjectFileImage) 'DYOF')
1849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define MAGIC_DYLIB_MOD ((NSModule) 'DYMO')
1859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* internal flags */
1879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define DL_IN_LIST 0x01
1889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* our mutex */
1909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic pthread_mutex_t dlcompat_mutex;
1919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Our thread specific storage
1929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
1939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic pthread_key_t dlerror_key;
1949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
1959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstruct dlthread
1969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
1979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int lockcnt;
1989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned char errset;
1999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	char errstr[ERR_STR_LEN];
2009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall};
2019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* This is our central data structure. Whenever a module is loaded via
2039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * SDL_OSX_dlopen(), we create such a struct.
2049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
2059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstruct dlstatus
2069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
2079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct dlstatus *next;		/* pointer to next element in the linked list */
2089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	NSModule module;
2099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const struct mach_header *lib;
2109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int refs;					/* reference count */
2119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int mode;					/* mode in which this module was loaded */
2129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dev_t device;
2139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	ino_t inode;
2149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int flags;					/* Any internal flags we may need */
2159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall};
2169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Head node of the dlstatus list */
2189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic struct dlstatus mainStatus = { 0, MAGIC_DYLIB_MOD, NULL, -1, RTLD_GLOBAL, 0, 0, 0 };
2199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic struct dlstatus *stqueue = &mainStatus;
2209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Storage for the last error message (used by dlerror()) */
2239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* static char err_str[ERR_STR_LEN]; */
2249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* static int err_filled = 0; */
2259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Prototypes to internal functions */
2279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void debug(const char *fmt, ...);
2289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void error(const char *str, ...);
2299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic const char *safegetenv(const char *s);
2309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic const char *searchList(void);
2319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic const char *getSearchPath(int i);
2329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic const char *getFullPath(int i, const char *file);
2339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic const struct stat *findFile(const char *file, const char **fullPath);
2349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int isValidStatus(struct dlstatus *status);
2359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic inline int isFlagSet(int mode, int flag);
2369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic struct dlstatus *lookupStatus(const struct stat *sbuf);
2379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void insertStatus(struct dlstatus *dls, const struct stat *sbuf);
2389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int promoteLocalToGlobal(struct dlstatus *dls);
2399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void *reference(struct dlstatus *dls, int mode);
2409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void *dlsymIntern(struct dlstatus *dls, const char *symbol, int canSetError);
2419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic struct dlstatus *allocStatus(void);
2429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic struct dlstatus *loadModule(const char *path, const struct stat *sbuf, int mode);
2439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic NSSymbol search_linked_libs(const struct mach_header *mh, const char *symbol);
2449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic const char *get_lib_name(const struct mach_header *mh);
2459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic const struct mach_header *get_mach_header_from_NSModule(NSModule mod);
2469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void dlcompat_init_func(void);
2479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic inline void dlcompat_init_check(void);
2489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic inline void dolock(void);
2499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic inline void dounlock(void);
2509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void dlerrorfree(void *data);
2519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void resetdlerror(void);
2529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic const struct mach_header *my_find_image(const char *name);
2539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic const struct mach_header *image_for_address(const void *address);
2549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic inline char *dyld_error_str(void);
2559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if FINK_BUILD
2579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Two Global Functions */
2589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void *dlsym_prepend_underscore(void *handle, const char *symbol);
2599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void *dlsym_auto_underscore(void *handle, const char *symbol);
2609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* And their _intern counterparts */
2629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void *dlsym_prepend_underscore_intern(void *handle, const char *symbol);
2639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void *dlsym_auto_underscore_intern(void *handle, const char *symbol);
2649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
2659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Functions */
2679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void debug(const char *fmt, ...)
2699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
2709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if DEBUG > 1
2719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	va_list arg;
2729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	va_start(arg, fmt);
2739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	fprintf(stderr, "DLDEBUG: ");
2749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	vfprintf(stderr, fmt, arg);
2759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	fprintf(stderr, "\n");
2769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	fflush(stderr);
2779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	va_end(arg);
2789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
2799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
2809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void error(const char *str, ...)
2829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
2839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	va_list arg;
2849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct dlthread  *tss;
2859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	char * err_str;
2869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	va_start(arg, str);
2879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	tss = pthread_getspecific(dlerror_key);
2889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	err_str = tss->errstr;
2899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_strlcpy(err_str, "dlcompat: ", ERR_STR_LEN);
2909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	vsnprintf(err_str + 10, ERR_STR_LEN - 10, str, arg);
2919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	va_end(arg);
2929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	debug("ERROR: %s\n", err_str);
2939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	tss->errset = 1;
2949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
2959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
2969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void warning(const char *str)
2979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
2989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if DEBUG > 0
2999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	fprintf(stderr, "WARNING: dlcompat: %s\n", str);
3009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
3019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
3029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic const char *safegetenv(const char *s)
3049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
3059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const char *ss = SDL_getenv(s);
3069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return ss ? ss : "";
3079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
3089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* because this is only used for debugging and error reporting functions, we
3109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * don't really care about how elegant it is... it could use the load
3119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * commands to find the install name of the library, but...
3129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
3139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic const char *get_lib_name(const struct mach_header *mh)
3149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
3159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned long count = _dyld_image_count();
3169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned long i;
3179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const char *val = NULL;
3189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (mh)
3199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
3209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		for (i = 0; i < count; i++)
3219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
3229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if (mh == _dyld_get_image_header(i))
3239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			{
3249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				val = _dyld_get_image_name(i);
3259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				break;
3269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
3279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
3289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
3299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return val;
3309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
3319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Returns the mach_header for the module bu going through all the loaded images
3339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * and finding the one with the same name as the module. There really ought to be
3349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * an api for doing this, would be faster, but there isn't one right now
3359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
3369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic const struct mach_header *get_mach_header_from_NSModule(NSModule mod)
3379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
3389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const char *mod_name = NSNameOfModule(mod);
3399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const struct mach_header *mh = NULL;
3409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned long count = _dyld_image_count();
3419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned long i;
3429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	debug("Module name: %s", mod_name);
3439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	for (i = 0; i < count; i++)
3449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
3459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (!SDL_strcmp(mod_name, _dyld_get_image_name(i)))
3469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
3479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			mh = _dyld_get_image_header(i);
3489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			break;
3499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
3509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
3519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return mh;
3529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
3539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Compute and return a list of all directories that we should search when
3569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * trying to locate a module. We first look at the values of LD_LIBRARY_PATH
3579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * and DYLD_LIBRARY_PATH, and then finally fall back to looking into
3589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * /usr/lib and /lib. Since both of the environments variables can contain a
3599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * list of colon seperated paths, we simply concat them and the two other paths
3609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * into one big string, which we then can easily parse.
3619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * Splitting this string into the actual path list is done by getSearchPath()
3629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
3639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic const char *searchList()
3649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
3659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	size_t buf_size;
3669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	static char *buf=NULL;
3679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const char *ldlp = safegetenv("LD_LIBRARY_PATH");
3689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const char *dyldlp = safegetenv("DYLD_LIBRARY_PATH");
3699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const char *stdpath = SDL_getenv("DYLD_FALLBACK_LIBRARY_PATH");
3709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!stdpath)
3719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		stdpath = "/usr/local/lib:/lib:/usr/lib";
3729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!buf)
3739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
3749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		buf_size = SDL_strlen(ldlp) + SDL_strlen(dyldlp) + SDL_strlen(stdpath) + 4;
3759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		buf = SDL_malloc(buf_size);
3769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_snprintf(buf, buf_size, "%s%s%s%s%s%c", dyldlp, (dyldlp[0] ? ":" : ""), ldlp, (ldlp[0] ? ":" : ""),
3779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				 stdpath, '\0');
3789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
3799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return buf;
3809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
3819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
3829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Returns the ith search path from the list as computed by searchList() */
3839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic const char *getSearchPath(int i)
3849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
3859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	static const char *list = 0;
3869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	static char **path = (char **)0;
3879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	static int end = 0;
3889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	static int numsize = MAX_SEARCH_PATHS;
3899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	static char **tmp;
3909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* So we can call SDL_free() in the "destructor" we use i=-1 to return the alloc'd array */
3919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (i == -1)
3929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
3939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		return (const char*)path;
3949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
3959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!path)
3969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
3979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		path = (char **)SDL_calloc(MAX_SEARCH_PATHS, sizeof(char **));
3989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
3999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!list && !end)
4009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		list = searchList();
4019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (i >= (numsize))
4029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
4039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		debug("Increasing size for long PATH");
4049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		tmp = (char **)SDL_calloc((MAX_SEARCH_PATHS + numsize), sizeof(char **));
4059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (tmp)
4069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
4079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_memcpy(tmp, path, sizeof(char **) * numsize);
4089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_free(path);
4099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			path = tmp;
4109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			numsize += MAX_SEARCH_PATHS;
4119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
4129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		else
4139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
4149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			return 0;
4159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
4169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
4179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	while (!path[i] && !end)
4199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
4209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		path[i] = strsep((char **)&list, ":");
4219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (path[i][0] == 0)
4239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			path[i] = 0;
4249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		end = (list == 0);
4259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
4269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return path[i];
4279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
4289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic const char *getFullPath(int i, const char *file)
4309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
4319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	static char buf[PATH_MAX];
4329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const char *path = getSearchPath(i);
4339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (path)
4349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
4359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_snprintf(buf, PATH_MAX, "%s/%s", path, file);
4369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
4379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return path ? buf : 0;
4389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
4399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Given a file name, try to determine the full path for that file. Starts
4419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * its search in the current directory, and then tries all paths in the
4429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * search list in the order they are specified there.
4439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
4449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic const struct stat *findFile(const char *file, const char **fullPath)
4459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
4469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int i = 0;
4479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	static struct stat sbuf;
4489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	char *fileName;
4499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	debug("finding file %s", file);
4509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	*fullPath = file;
4519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (0 == stat(file, &sbuf))
4529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		return &sbuf;
4539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (SDL_strchr(file, '/'))
4549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		return 0;				/* If the path had a / we don't look in env var places */
4559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	fileName = NULL;
4569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!fileName)
4579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		fileName = (char *)file;
4589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	while ((*fullPath = getFullPath(i++, fileName)))
4599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
4609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (0 == stat(*fullPath, &sbuf))
4619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			return &sbuf;
4629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
4639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	;
4649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return 0;
4659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
4669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Determine whether a given dlstatus is valid or not */
4689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int isValidStatus(struct dlstatus *status)
4699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
4709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Walk the list to verify status is contained in it */
4719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct dlstatus *dls = stqueue;
4729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	while (dls && status != dls)
4739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		dls = dls->next;
4749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (dls == 0)
4759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		error("invalid handle");
4769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	else if ((dls->module == 0) || (dls->refs == 0))
4779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		error("handle to closed library");
4789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	else
4799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		return TRUE;
4809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return FALSE;
4819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
4829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic inline int isFlagSet(int mode, int flag)
4849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
4859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return (mode & flag) == flag;
4869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
4879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic struct dlstatus *lookupStatus(const struct stat *sbuf)
4899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
4909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct dlstatus *dls = stqueue;
4919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	debug("looking for status");
4929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	while (dls && ( /* isFlagSet(dls->mode, RTLD_UNSHARED) */ 0
4939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				   || sbuf->st_dev != dls->device || sbuf->st_ino != dls->inode))
4949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		dls = dls->next;
4959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return dls;
4969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
4979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
4989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void insertStatus(struct dlstatus *dls, const struct stat *sbuf)
4999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
5009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	debug("inserting status");
5019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dls->inode = sbuf->st_ino;
5029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dls->device = sbuf->st_dev;
5039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dls->refs = 0;
5049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dls->mode = 0;
5059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ((dls->flags & DL_IN_LIST) == 0)
5069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
5079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		dls->next = stqueue;
5089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		stqueue = dls;
5099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		dls->flags |= DL_IN_LIST;
5109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
5119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
5129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic struct dlstatus *allocStatus()
5149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
5159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct dlstatus *dls;
5169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef REUSE_STATUS
5179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dls = stqueue;
5189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	while (dls && dls->module)
5199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		dls = dls->next;
5209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!dls)
5219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
5229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		dls = SDL_calloc(sizeof(*dls),1);
5239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return dls;
5249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
5259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int promoteLocalToGlobal(struct dlstatus *dls)
5279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
5289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	static int (*p) (NSModule module) = 0;
5299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	debug("promoting");
5309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!p)
5319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		_dyld_func_lookup("__dyld_NSMakePrivateModulePublic", (void **)&p);
5329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return (dls->module == MAGIC_DYLIB_MOD) || (p && p(dls->module));
5339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
5349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void *reference(struct dlstatus *dls, int mode)
5369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
5379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (dls)
5389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
5399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (dls->module == MAGIC_DYLIB_MOD && isFlagSet(mode, RTLD_LOCAL))
5409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
5419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			warning("trying to open a .dylib with RTLD_LOCAL");
5429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			error("unable to open a .dylib with RTLD_LOCAL");
5439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			return NULL;
5449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
5459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (isFlagSet(mode, RTLD_GLOBAL) &&
5469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			!isFlagSet(dls->mode, RTLD_GLOBAL) && !promoteLocalToGlobal(dls))
5479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
5489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			error("unable to promote local module to global");
5499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			return NULL;
5509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
5519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		dls->mode |= mode;
5529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		dls->refs++;
5539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
5549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	else
5559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		debug("reference called with NULL argument");
5569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return dls;
5589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
5599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic const struct mach_header *my_find_image(const char *name)
5619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
5629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const struct mach_header *mh = 0;
5639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const char *id = NULL;
5649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int i = _dyld_image_count();
5659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int j;
5669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	mh = (struct mach_header *)
5679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		dyld_NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED |
5689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall						NSADDIMAGE_OPTION_RETURN_ON_ERROR);
5699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!mh)
5709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
5719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		for (j = 0; j < i; j++)
5729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
5739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			id = _dyld_get_image_name(j);
5749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if (!SDL_strcmp(id, name))
5759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			{
5769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				mh = _dyld_get_image_header(j);
5779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				break;
5789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
5799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
5809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
5819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return mh;
5829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
5839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
5849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
5859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * dyld adds libraries by first adding the directly dependant libraries in link order, and
5869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * then adding the dependencies for those libraries, so we should do the same... but we don't
5879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * bother adding the extra dependencies, if the symbols are neither in the loaded image nor
5889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * any of it's direct dependencies, then it probably isn't there.
5899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
5909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic NSSymbol search_linked_libs(const struct mach_header * mh, const char *symbol)
5919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
5929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned int n;
5939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct load_command *lc = 0;
5949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct mach_header *wh;
5959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	NSSymbol nssym = 0;
5969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage)
5979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
5989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		lc = (struct load_command *)((char *)mh + sizeof(struct mach_header));
5999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		for (n = 0; n < mh->ncmds; n++, lc = (struct load_command *)((char *)lc + lc->cmdsize))
6009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
6019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd))
6029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			{
6039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				if ((wh = (struct mach_header *)
6049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					 my_find_image((char *)(((struct dylib_command *)lc)->dylib.name.offset +
6059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall											(char *)lc))))
6069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				{
6079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					if (dyld_NSIsSymbolNameDefinedInImage(wh, symbol))
6089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					{
6099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall						nssym = dyld_NSLookupSymbolInImage(wh,
6109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall														   symbol,
6119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall														   NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
6129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall														   NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
6139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall						break;
6149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					}
6159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				}
6169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
6179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
6189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ((!nssym) && NSIsSymbolNameDefined(symbol))
6199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
6209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			/* I've never seen this debug message...*/
6219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			debug("Symbol \"%s\" is defined but was not found", symbol);
6229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
6239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
6249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return nssym;
6259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
6269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Up to the caller to SDL_free() returned string */
6289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic inline char *dyld_error_str()
6299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
6309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	NSLinkEditErrors dylder;
6319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int dylderno;
6329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const char *dylderrstr;
6339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const char *dyldfile;
6349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	char* retStr = NULL;
6359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	NSLinkEditError(&dylder, &dylderno, &dyldfile, &dylderrstr);
6369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (dylderrstr && *dylderrstr)
6379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
6389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		retStr = SDL_strdup(dylderrstr);
6399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
6409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return retStr;
6419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
6429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void *dlsymIntern(struct dlstatus *dls, const char *symbol, int canSetError)
6449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
6459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  NSSymbol nssym = 0;
6469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef __GCC__
6479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	void *caller = __builtin_return_address(1);	/* Be *very* careful about inlining */
6489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#else
6499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	void *caller = NULL;
6509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
6519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const struct mach_header *caller_mh = 0;
6529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	char *savedErrorStr = NULL;
6539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	resetdlerror();
6549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifndef RTLD_SELF
6559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#define	RTLD_SELF		((void *) -3)
6569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
6579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (NULL == dls)
6589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		dls = RTLD_SELF;
6599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ((RTLD_NEXT == dls) || (RTLD_SELF == dls))
6609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
6619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage && caller)
6629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		  {
6639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			caller_mh = image_for_address(caller);
6649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if (RTLD_SELF == dls)
6659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			{
6669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				/* FIXME: We should be using the NSModule api, if SELF is an MH_BUNDLE
6679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				 * But it appears to work anyway, and looking at the code in dyld_libfuncs.c
6689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				 * this is acceptable.
6699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				 */
6709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				if (dyld_NSIsSymbolNameDefinedInImage(caller_mh, symbol))
6719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				{
6729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					nssym = dyld_NSLookupSymbolInImage(caller_mh,
6739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall													   symbol,
6749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall													   NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
6759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall													   NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
6769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				}
6779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
6789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if (!nssym)
6799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			{
6809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				if (RTLD_SELF == dls)
6819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					savedErrorStr = dyld_error_str();
6829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				nssym = search_linked_libs(caller_mh, symbol);
6839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
6849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
6859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		else
6869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
6879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if (canSetError)
6889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				error("RTLD_SELF and RTLD_NEXT are not supported");
6899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			return NULL;
6909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
6919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
6929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!nssym)
6939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
6949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
6959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (RTLD_DEFAULT == dls)
6969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
6979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			dls = &mainStatus;
6989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
6999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (!isValidStatus(dls))
7009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			return NULL;
7019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (dls->module != MAGIC_DYLIB_MOD)
7039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
7049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			nssym = NSLookupSymbolInModule(dls->module, symbol);
7059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if (!nssym && NSIsSymbolNameDefined(symbol))
7069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			{
7079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				debug("Searching dependencies");
7089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				savedErrorStr = dyld_error_str();
7099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				nssym = search_linked_libs(get_mach_header_from_NSModule(dls->module), symbol);
7109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
7119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
7129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		else if (dls->lib && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage)
7139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
7149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if (dyld_NSIsSymbolNameDefinedInImage(dls->lib, symbol))
7159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			{
7169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				nssym = dyld_NSLookupSymbolInImage(dls->lib,
7179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall												   symbol,
7189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall												   NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
7199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall												   NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
7209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
7219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			else if (NSIsSymbolNameDefined(symbol))
7229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			{
7239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				debug("Searching dependencies");
7249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				savedErrorStr = dyld_error_str();
7259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				nssym = search_linked_libs(dls->lib, symbol);
7269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
7279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
7289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		else if (dls->module == MAGIC_DYLIB_MOD)
7299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
7309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			/* Global context, use NSLookupAndBindSymbol */
7319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if (NSIsSymbolNameDefined(symbol))
7329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			{
7339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				/* There doesn't seem to be a return on error option for this call???
7349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				   this is potentially broken, if binding fails, it will improperly
7359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				   exit the application. */
7369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				nssym = NSLookupAndBindSymbol(symbol);
7379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
7389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			else
7399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			{
7409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				if (savedErrorStr)
7419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					SDL_free(savedErrorStr);
7429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				savedErrorStr = SDL_malloc(256);
7439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				SDL_snprintf(savedErrorStr, 256, "Symbol \"%s\" not in global context",symbol);
7449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
7459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
7469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
7479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Error reporting */
7489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!nssym)
7499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
7509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (!savedErrorStr || !SDL_strlen(savedErrorStr))
7519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
7529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if (savedErrorStr)
7539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				SDL_free(savedErrorStr);
7549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			savedErrorStr = SDL_malloc(256);
7559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_snprintf(savedErrorStr, 256,"Symbol \"%s\" not found",symbol);
7569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
7579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (canSetError)
7589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
7599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			error(savedErrorStr);
7609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
7619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		else
7629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
7639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			debug(savedErrorStr);
7649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
7659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (savedErrorStr)
7669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_free(savedErrorStr);
7679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		return NULL;
7689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
7699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return NSAddressOfSymbol(nssym);
7709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
7719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic struct dlstatus *loadModule(const char *path, const struct stat *sbuf, int mode)
7739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
7749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	NSObjectFileImage ofi = 0;
7759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	NSObjectFileImageReturnCode ofirc;
7769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct dlstatus *dls;
7779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	NSLinkEditErrors ler;
7789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int lerno;
7799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const char *errstr;
7809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const char *file;
7819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	void (*init) (void);
7829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
7839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	ofirc = NSCreateObjectFileImageFromFile(path, &ofi);
7849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	switch (ofirc)
7859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
7869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		case NSObjectFileImageSuccess:
7879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			break;
7889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		case NSObjectFileImageInappropriateFile:
7899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage)
7909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			{
7919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				if (isFlagSet(mode, RTLD_LOCAL))
7929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				{
7939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					warning("trying to open a .dylib with RTLD_LOCAL");
7949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					error("unable to open this file with RTLD_LOCAL");
7959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					return NULL;
7969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				}
7979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
7989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			else
7999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			{
8009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				error("opening this file is unsupported on this system");
8019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				return NULL;
8029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
8039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			break;
8049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		case NSObjectFileImageFailure:
8059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			error("object file setup failure");
8069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			return NULL;
8079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		case NSObjectFileImageArch:
8089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			error("no object for this architecture");
8099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			return NULL;
8109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		case NSObjectFileImageFormat:
8119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			error("bad object file format");
8129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			return NULL;
8139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		case NSObjectFileImageAccess:
8149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			error("can't read object file");
8159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			return NULL;
8169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		default:
8179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			error("unknown error from NSCreateObjectFileImageFromFile()");
8189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			return NULL;
8199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
8209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dls = lookupStatus(sbuf);
8219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!dls)
8229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
8239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		dls = allocStatus();
8249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
8259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!dls)
8269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
8279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		error("unable to allocate memory");
8289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		return NULL;
8299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
8309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	//	dls->lib = 0;
8319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (ofirc == NSObjectFileImageInappropriateFile)
8329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
8339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ((dls->lib = dyld_NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR)))
8349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
8359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			debug("Dynamic lib loaded at %ld", dls->lib);
8369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			ofi = MAGIC_DYLIB_OFI;
8379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			dls->module = MAGIC_DYLIB_MOD;
8389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			ofirc = NSObjectFileImageSuccess;
8399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			/* Although it is possible with a bit of work to modify this so it works and
8409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			   functions with RTLD_NOW, I don't deem it necessary at the moment */
8419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
8429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (!(dls->module))
8439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
8449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			NSLinkEditError(&ler, &lerno, &file, &errstr);
8459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if (!errstr || (!SDL_strlen(errstr)))
8469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				error("Can't open this file type");
8479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			else
8489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				error(errstr);
8499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if ((dls->flags & DL_IN_LIST) == 0)
8509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			{
8519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				SDL_free(dls);
8529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
8539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			return NULL;
8549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
8559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
8569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	else
8579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
8589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		dls->module = NSLinkModule(ofi, path,
8599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall								   NSLINKMODULE_OPTION_RETURN_ON_ERROR |
8609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall								   NSLINKMODULE_OPTION_PRIVATE |
8619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall								   (isFlagSet(mode, RTLD_NOW) ? NSLINKMODULE_OPTION_BINDNOW : 0));
8629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		NSDestroyObjectFileImage(ofi);
8639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (dls->module)
8649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
8659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			dls->lib = get_mach_header_from_NSModule(dls->module);
8669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
8679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
8689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!dls->module)
8699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
8709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		NSLinkEditError(&ler, &lerno, &file, &errstr);
8719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ((dls->flags & DL_IN_LIST) == 0)
8729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
8739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			SDL_free(dls);
8749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
8759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		error(errstr);
8769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		return NULL;
8779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
8789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	insertStatus(dls, sbuf);
8809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dls = reference(dls, mode);
8819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ((init = dlsymIntern(dls, "__init", 0)))
8829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
8839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		debug("calling _init()");
8849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		init();
8859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
8869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return dls;
8879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
8889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallinline static void dlcompat_init_check(void)
8909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
8919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	static pthread_mutex_t l = PTHREAD_MUTEX_INITIALIZER;
8929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	static int init_done = 0;
8939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
8949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	pthread_mutex_lock(&l);
8959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!init_done) {
8969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		dlcompat_init_func();
8979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		init_done = 1;
8989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
8999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	pthread_mutex_unlock(&l);
9009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
9019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void dlcompat_init_func(void)
9039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
9049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall        _dyld_func_lookup("__dyld_NSAddImage", (void **)&dyld_NSAddImage);
9059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	_dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",
9069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			  (void **)&dyld_NSIsSymbolNameDefinedInImage);
9079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	_dyld_func_lookup("__dyld_NSLookupSymbolInImage", (void **)&dyld_NSLookupSymbolInImage);
9089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (pthread_mutex_init(&dlcompat_mutex, NULL))
9099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    exit(1);
9109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (pthread_key_create(&dlerror_key, &dlerrorfree))
9119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	    exit(1);
9129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
9139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void resetdlerror()
9159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
9169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct dlthread *tss;
9179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	tss = pthread_getspecific(dlerror_key);
9189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	tss->errset = 0;
9199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
9209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void dlerrorfree(void *data)
9229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
9239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	SDL_free(data);
9249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
9259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* We kind of want a recursive lock here, but meet a little trouble
9279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * because they are not available pre OS X 10.2, so we fake it
9289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * using thread specific storage to keep a lock count
9299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
9309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic inline void dolock(void)
9319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
9329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int err = 0;
9339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct dlthread *tss;
9349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dlcompat_init_check();
9359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	tss = pthread_getspecific(dlerror_key);
9369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!tss)
9379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
9389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		tss = SDL_malloc(sizeof(struct dlthread));
9399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		tss->lockcnt = 0;
9409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		tss->errset = 0;
9419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (pthread_setspecific(dlerror_key, tss))
9429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
9439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			fprintf(stderr,"dlcompat: pthread_setspecific failed\n");
9449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			exit(1);
9459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
9469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
9479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!tss->lockcnt)
9489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		err = pthread_mutex_lock(&dlcompat_mutex);
9499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	tss->lockcnt = tss->lockcnt +1;
9509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (err)
9519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		exit(err);
9529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
9539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic inline void dounlock(void)
9559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
9569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int err = 0;
9579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct dlthread *tss;
9589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	tss = pthread_getspecific(dlerror_key);
9599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	tss->lockcnt = tss->lockcnt -1;
9609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!tss->lockcnt)
9619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		err = pthread_mutex_unlock(&dlcompat_mutex);
9629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (err)
9639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		exit(err);
9649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
9659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void *SDL_OSX_dlopen(const char *path, int mode)
9679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
9689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const struct stat *sbuf;
9699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct dlstatus *dls;
9709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const char *fullPath;
9719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
9729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dolock();
9739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	resetdlerror();
9749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!path)
9759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
9769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		dls = &mainStatus;
9779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		goto dlopenok;
9789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
9799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!(sbuf = findFile(path, &fullPath)))
9809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
9819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		error("file \"%s\" not found", path);
9829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		goto dlopenerror;
9839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
9849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	/* Now checks that it hasn't been closed already */
9859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ((dls = lookupStatus(sbuf)) && (dls->refs > 0))
9869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
9879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* debug("status found"); */
9889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		dls = reference(dls, mode);
9899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		goto dlopenok;
9909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
9919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef 	RTLD_NOLOAD
9929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (isFlagSet(mode, RTLD_NOLOAD))
9939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
9949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		error("no existing handle and RTLD_NOLOAD specified");
9959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		goto dlopenerror;
9969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
9979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
9989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (isFlagSet(mode, RTLD_LAZY) && isFlagSet(mode, RTLD_NOW))
9999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
10009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		error("how can I load something both RTLD_LAZY and RTLD_NOW?");
10019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		goto dlopenerror;
10029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
10039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dls = loadModule(fullPath, sbuf, mode);
10049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  dlopenok:
10069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dounlock();
10079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return (void *)dls;
10089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  dlopenerror:
10099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dounlock();
10109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return NULL;
10119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
10129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if !FINK_BUILD
10149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void *SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol)
10159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
10169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int sym_len = SDL_strlen(symbol);
10179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	void *value = NULL;
10189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	char *malloc_sym = NULL;
10199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dolock();
10209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	malloc_sym = SDL_malloc(sym_len + 2);
10219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (malloc_sym)
10229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
10239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol);
10249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		value = dlsymIntern(handle, malloc_sym, 1);
10259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_free(malloc_sym);
10269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
10279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	else
10289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
10299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		error("Unable to allocate memory");
10309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		goto dlsymerror;
10319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
10329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dounlock();
10339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return value;
10349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  dlsymerror:
10359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dounlock();
10369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return NULL;
10379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
10389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
10399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if FINK_BUILD
10419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void *dlsym_prepend_underscore(void *handle, const char *symbol)
10439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
10449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	void *answer;
10459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dolock();
10469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	answer = dlsym_prepend_underscore_intern(handle, symbol);
10479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dounlock();
10489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return answer;
10499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
10509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void *dlsym_prepend_underscore_intern(void *handle, const char *symbol)
10529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
10539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
10549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *	A quick and easy way for porting packages which call dlsym(handle,"sym")
10559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *	If the porter adds -Ddlsym=dlsym_prepend_underscore to the CFLAGS then
10569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *	this function will be called, and will add the required underscore.
10579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *
10589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *	Note that I haven't figured out yet which should be "standard", prepend
10599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *	the underscore always, or not at all. These global functions need to go away
10609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall *	for opendarwin.
10619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
10629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int sym_len = SDL_strlen(symbol);
10639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	void *value = NULL;
10649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	char *malloc_sym = NULL;
10659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	malloc_sym = SDL_malloc(sym_len + 2);
10669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (malloc_sym)
10679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
10689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol);
10699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		value = dlsymIntern(handle, malloc_sym, 1);
10709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_free(malloc_sym);
10719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
10729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	else
10739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
10749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		error("Unable to allocate memory");
10759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
10769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return value;
10779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
10789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void *dlsym_auto_underscore(void *handle, const char *symbol)
10809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
10819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	void *answer;
10829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dolock();
10839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	answer = dlsym_auto_underscore_intern(handle, symbol);
10849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dounlock();
10859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return answer;
10869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
10889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void *dlsym_auto_underscore_intern(void *handle, const char *symbol)
10899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
10909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct dlstatus *dls = handle;
10919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	void *addr = 0;
10929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	addr = dlsymIntern(dls, symbol, 0);
10939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!addr)
10949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		addr = dlsym_prepend_underscore_intern(handle, symbol);
10959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return addr;
10969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
10979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
10999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic void *SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol)
11009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
11019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct dlstatus *dls = handle;
11029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	void *addr = 0;
11039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dolock();
11049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	addr = dlsymIntern(dls, symbol, 1);
11059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dounlock();
11069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return addr;
11079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
11089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
11099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int SDL_OSX_dlclose(void *handle)
11119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
11129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct dlstatus *dls = handle;
11139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dolock();
11149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	resetdlerror();
11159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!isValidStatus(dls))
11169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
11179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		goto dlcloseerror;
11189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
11199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (dls->module == MAGIC_DYLIB_MOD)
11209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
11219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		const char *name;
11229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (!dls->lib)
11239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
11249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			name = "global context";
11259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
11269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		else
11279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
11289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			name = get_lib_name(dls->lib);
11299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
11309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		warning("trying to close a .dylib!");
11319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		error("Not closing \"%s\" - dynamic libraries cannot be closed", name);
11329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		goto dlcloseerror;
11339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
11349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!dls->module)
11359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
11369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		error("module already closed");
11379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		goto dlcloseerror;
11389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
11399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (dls->refs == 1)
11419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
11429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		unsigned long options = 0;
11439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		void (*fini) (void);
11449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if ((fini = dlsymIntern(dls, "__fini", 0)))
11459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
11469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			debug("calling _fini()");
11479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			fini();
11489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
11499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		options |= NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
11509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#ifdef RTLD_NODELETE
11519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (isFlagSet(dls->mode, RTLD_NODELETE))
11529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			options |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
11539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
11549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (!NSUnLinkModule(dls->module, options))
11559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
11569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			error("unable to unlink module");
11579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			goto dlcloseerror;
11589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
11599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		dls->refs--;
11609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		dls->module = 0;
11619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		/* Note: the dlstatus struct dls is neither removed from the list
11629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		 * nor is the memory it occupies freed. This shouldn't pose a
11639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		 * problem in mostly all cases, though.
11649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		 */
11659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
11669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dounlock();
11679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return 0;
11689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  dlcloseerror:
11699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dounlock();
11709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return 1;
11719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
11729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic const char *SDL_OSX_dlerror(void)
11749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
11759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct dlthread  *tss;
11769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const char * err_str = NULL;
11779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dlcompat_init_check();
11789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	tss = pthread_getspecific(dlerror_key);
11799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (tss != NULL && tss->errset != 0) {
11809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		tss->errset = 0;
11819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		err_str = tss->errstr;
11829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
11839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return (err_str);
11849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
11859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
11869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Given an address, return the mach_header for the image containing it
11879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * or zero if the given address is not contained in any loaded images.
11889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
11899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic const struct mach_header *image_for_address(const void *address)
11909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
11919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned long i;
11929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned long j;
11939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned long count = _dyld_image_count();
11949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const struct mach_header *mh = 0;
11959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct load_command *lc = 0;
11969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned long addr = 0;
11979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	for (i = 0; i < count; i++)
11989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
11999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		addr = (unsigned long)address - _dyld_get_image_vmaddr_slide(i);
12009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		mh = _dyld_get_image_header(i);
12019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (mh)
12029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
12039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			lc = (struct load_command *)((char *)mh + sizeof(struct mach_header));
12049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize))
12059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			{
12069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				if (LC_SEGMENT == lc->cmd &&
12079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					addr >= ((struct segment_command *)lc)->vmaddr &&
12089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					addr <
12099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					((struct segment_command *)lc)->vmaddr + ((struct segment_command *)lc)->vmsize)
12109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				{
12119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					goto image_found;
12129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				}
12139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
12149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
12159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		mh = 0;
12169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
12179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  image_found:
12189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return mh;
12199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
12209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if 0 /* unused */
12229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic int SDL_OSX_dladdr(const void * dl_restrict p, SDL_OSX_Dl_info * dl_restrict info)
12239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
12249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
12259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	FIXME: USe the routine image_for_address.
12269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall*/
12279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned long i;
12289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned long j;
12299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned long count = _dyld_image_count();
12309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct mach_header *mh = 0;
12319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	struct load_command *lc = 0;
12329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned long addr = NULL;
12339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	unsigned long table_off = (unsigned long)0;
12349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int found = 0;
12359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!info)
12369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		return 0;
12379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dolock();
12389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	resetdlerror();
12399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	info->dli_fname = 0;
12409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	info->dli_fbase = 0;
12419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	info->dli_sname = 0;
12429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	info->dli_saddr = 0;
12439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* Some of this was swiped from code posted by Douglas Davidson <ddavidso AT apple DOT com>
12449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * to darwin-development AT lists DOT apple DOT com and slightly modified
12459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
12469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	for (i = 0; i < count; i++)
12479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
12489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		addr = (unsigned long)p - _dyld_get_image_vmaddr_slide(i);
12499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		mh = _dyld_get_image_header(i);
12509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (mh)
12519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
12529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			lc = (struct load_command *)((char *)mh + sizeof(struct mach_header));
12539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize))
12549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			{
12559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				if (LC_SEGMENT == lc->cmd &&
12569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					addr >= ((struct segment_command *)lc)->vmaddr &&
12579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					addr <
12589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					((struct segment_command *)lc)->vmaddr + ((struct segment_command *)lc)->vmsize)
12599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				{
12609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					info->dli_fname = _dyld_get_image_name(i);
12619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					info->dli_fbase = (void *)mh;
12629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					found = 1;
12639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					break;
12649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				}
12659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
12669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if (found)
12679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				break;
12689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
12699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
12709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (!found)
12719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
12729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		dounlock();
12739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		return 0;
12749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
12759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	lc = (struct load_command *)((char *)mh + sizeof(struct mach_header));
12769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize))
12779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
12789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (LC_SEGMENT == lc->cmd)
12799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
12809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if (!SDL_strcmp(((struct segment_command *)lc)->segname, "__LINKEDIT"))
12819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				break;
12829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
12839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
12849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	table_off =
12859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		((unsigned long)((struct segment_command *)lc)->vmaddr) -
12869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		((unsigned long)((struct segment_command *)lc)->fileoff) + _dyld_get_image_vmaddr_slide(i);
12879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	debug("table off %x", table_off);
12889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	lc = (struct load_command *)((char *)mh + sizeof(struct mach_header));
12909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize))
12919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
12929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		if (LC_SYMTAB == lc->cmd)
12939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		{
12949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
12959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			struct nlist *symtable = (struct nlist *)(((struct symtab_command *)lc)->symoff + table_off);
12969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			unsigned long numsyms = ((struct symtab_command *)lc)->nsyms;
12979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			struct nlist *nearest = NULL;
12989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			unsigned long diff = 0xffffffff;
12999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			unsigned long strtable = (unsigned long)(((struct symtab_command *)lc)->stroff + table_off);
13009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			debug("symtable %x", symtable);
13019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			for (i = 0; i < numsyms; i++)
13029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			{
13039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				/* Ignore the following kinds of Symbols */
13049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				if ((!symtable->n_value)	/* Undefined */
13059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					|| (symtable->n_type >= N_PEXT)	/* Debug symbol */
13069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					|| (!(symtable->n_type & N_EXT))	/* Local Symbol */
13079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					)
13089682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				{
13099682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					symtable++;
13109682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					continue;
13119682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				}
13129682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				if ((addr >= symtable->n_value) && (diff >= (symtable->n_value - addr)))
13139682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				{
13149682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					diff = (unsigned long)symtable->n_value - addr;
13159682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall					nearest = symtable;
13169682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				}
13179682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				symtable++;
13189682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
13199682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			if (nearest)
13209682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			{
13219682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				info->dli_saddr = nearest->n_value + ((void *)p - addr);
13229682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall				info->dli_sname = (char *)(strtable + nearest->n_un.n_strx);
13239682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall			}
13249682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		}
13259682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
13269682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dounlock();
13279682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return 1;
13289682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
13299682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
13309682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13319682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/*
13329682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * Implement the dlfunc() interface, which behaves exactly the same as
13339682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * dlsym() except that it returns a function pointer instead of a data
13349682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * pointer.  This can be used by applications to avoid compiler warnings
13359682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * about undefined behavior, and is intended as prior art for future
13369682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * POSIX standardization.  This function requires that all pointer types
13379682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * have the same representation, which is true on all platforms FreeBSD
13389682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall * runs on, but is not guaranteed by the C standard.
13399682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall */
13409682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#if 0
13419682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallstatic dlfunc_t SDL_OSX_dlfunc(void * dl_restrict handle, const char * dl_restrict symbol)
13429682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
13439682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	union
13449682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
13459682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		void *d;
13469682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		dlfunc_t f;
13479682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	} rv;
13489682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	int sym_len = SDL_strlen(symbol);
13499682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	char *malloc_sym = NULL;
13509682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dolock();
13519682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	malloc_sym = SDL_malloc(sym_len + 2);
13529682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if (malloc_sym)
13539682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
13549682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol);
13559682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		rv.d = dlsymIntern(handle, malloc_sym, 1);
13569682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_free(malloc_sym);
13579682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
13589682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	else
13599682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	{
13609682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		error("Unable to allocate memory");
13619682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		goto dlfuncerror;
13629682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
13639682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dounlock();
13649682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return rv.f;
13659682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall  dlfuncerror:
13669682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	dounlock();
13679682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return NULL;
13689682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
13699682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif
13709682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13719682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13729682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13739682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* dlcompat ends, here's the SDL interface...  --ryan.  */
13749682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13759682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13769682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13779682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall/* System dependent library loading routines                           */
13789682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13799682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#include "SDL_loadso.h"
13809682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13819682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid *SDL_LoadObject(const char *sofile)
13829682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
13839682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	void *handle = SDL_OSX_dlopen(sofile, RTLD_NOW);
13849682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	const char *loaderror = SDL_OSX_dlerror();
13859682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( handle == NULL ) {
13869682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_SetError("Failed loading %s: %s", sofile, loaderror);
13879682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
13889682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return(handle);
13899682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
13909682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
13919682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid *SDL_LoadFunction(void *handle, const char *name)
13929682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
13939682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	void *symbol = SDL_OSX_dlsym(handle, name);
13949682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( symbol == NULL ) {
13959682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_SetError("Failed loading %s: %s", name, SDL_OSX_dlerror());
13969682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
13979682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	return(symbol);
13989682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
13999682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14009682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hallvoid SDL_UnloadObject(void *handle)
14019682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall{
14029682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	if ( handle != NULL ) {
14039682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall		SDL_OSX_dlclose(handle);
14049682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall	}
14059682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall}
14069682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall
14079682c8870b8ff5e4ac2e4c70b759f791c6f38c1fJesse Hall#endif /* SDL_LOADSO_DLCOMPAT */
1408