Mercurial > sdl-ios-xcode
comparison src/loadso/macosx/SDL_dlcompat.c @ 1662:782fd950bd46 SDL-1.3
Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API.
WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid.
The code is now run through a consistent indent format:
indent -i4 -nut -nsc -br -ce
The headers are being converted to automatically generate doxygen documentation.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 28 May 2006 13:04:16 +0000 |
parents | 14717b52abc0 |
children | 4da1ee79c9af |
comparison
equal
deleted
inserted
replaced
1661:281d3f4870e5 | 1662:782fd950bd46 |
---|---|
83 #define __BSD_VISIBLE 1 | 83 #define __BSD_VISIBLE 1 |
84 #endif | 84 #endif |
85 | 85 |
86 /*include "dlfcn.h"*/ | 86 /*include "dlfcn.h"*/ |
87 #ifdef __cplusplus | 87 #ifdef __cplusplus |
88 extern "C" { | 88 extern "C" |
89 { | |
89 #endif | 90 #endif |
90 | 91 |
91 #if defined (__GNUC__) && __GNUC__ > 3 | 92 #if defined (__GNUC__) && __GNUC__ > 3 |
92 #define dl_restrict __restrict | 93 #define dl_restrict __restrict |
93 #else | 94 #else |
97 #if 0 | 98 #if 0 |
98 #ifndef _POSIX_SOURCE | 99 #ifndef _POSIX_SOURCE |
99 /* | 100 /* |
100 * Structure filled in by dladdr(). | 101 * Structure filled in by dladdr(). |
101 */ | 102 */ |
102 typedef struct SDL_OSX_dl_info { | 103 typedef struct SDL_OSX_dl_info |
103 const char *dli_fname; /* Pathname of shared object */ | 104 { |
104 void *dli_fbase; /* Base address of shared object */ | 105 const char *dli_fname; /* Pathname of shared object */ |
105 const char *dli_sname; /* Name of nearest symbol */ | 106 void *dli_fbase; /* Base address of shared object */ |
106 void *dli_saddr; /* Address of nearest symbol */ | 107 const char *dli_sname; /* Name of nearest symbol */ |
107 } SDL_OSX_Dl_info; | 108 void *dli_saddr; /* Address of nearest symbol */ |
108 | 109 } SDL_OSX_Dl_info; |
109 static int SDL_OSX_dladdr(const void * dl_restrict, SDL_OSX_Dl_info * dl_restrict); | 110 |
110 #endif /* ! _POSIX_SOURCE */ | 111 static int SDL_OSX_dladdr (const void *dl_restrict, |
111 #endif /* 0 */ | 112 SDL_OSX_Dl_info * dl_restrict); |
112 | 113 #endif /* ! _POSIX_SOURCE */ |
113 static int SDL_OSX_dlclose(void * handle); | 114 #endif /* 0 */ |
114 static const char * SDL_OSX_dlerror(void); | 115 |
115 static void * SDL_OSX_dlopen(const char *path, int mode); | 116 static int SDL_OSX_dlclose (void *handle); |
116 static void * SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol); | 117 static const char *SDL_OSX_dlerror (void); |
118 static void *SDL_OSX_dlopen (const char *path, int mode); | |
119 static void *SDL_OSX_dlsym (void *dl_restrict handle, | |
120 const char *dl_restrict symbol); | |
117 | 121 |
118 #define RTLD_LAZY 0x1 | 122 #define RTLD_LAZY 0x1 |
119 #define RTLD_NOW 0x2 | 123 #define RTLD_NOW 0x2 |
120 #define RTLD_LOCAL 0x4 | 124 #define RTLD_LOCAL 0x4 |
121 #define RTLD_GLOBAL 0x8 | 125 #define RTLD_GLOBAL 0x8 |
125 #define RTLD_NODELETE 0x80 | 129 #define RTLD_NODELETE 0x80 |
126 | 130 |
127 /* | 131 /* |
128 * Special handle arguments for SDL_OSX_dlsym(). | 132 * Special handle arguments for SDL_OSX_dlsym(). |
129 */ | 133 */ |
130 #define RTLD_NEXT ((void *) -1) /* Search subsequent objects. */ | 134 #define RTLD_NEXT ((void *) -1) /* Search subsequent objects. */ |
131 #define RTLD_DEFAULT ((void *) -2) /* Use default search algorithm. */ | 135 #define RTLD_DEFAULT ((void *) -2) /* Use default search algorithm. */ |
132 #endif /* ! _POSIX_SOURCE */ | 136 #endif /* ! _POSIX_SOURCE */ |
133 | 137 |
134 #ifdef __cplusplus | 138 #ifdef __cplusplus |
135 } | 139 } |
136 #endif | 140 #endif |
137 | 141 |
160 #endif | 164 #endif |
161 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR | 165 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR |
162 #define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4 | 166 #define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4 |
163 #endif | 167 #endif |
164 /* These symbols will be looked for in dyld */ | 168 /* These symbols will be looked for in dyld */ |
165 static const struct mach_header *(*dyld_NSAddImage) (const char *, unsigned long) = 0; | 169 static const struct mach_header *(*dyld_NSAddImage) (const char *, |
166 static int (*dyld_NSIsSymbolNameDefinedInImage) (const struct mach_header *, const char *) = 0; | 170 unsigned long) = 0; |
167 static NSSymbol(*dyld_NSLookupSymbolInImage) | 171 static int (*dyld_NSIsSymbolNameDefinedInImage) (const struct mach_header *, |
168 (const struct mach_header *, const char *, unsigned long) = 0; | 172 const char *) = 0; |
173 static NSSymbol (*dyld_NSLookupSymbolInImage) (const struct mach_header *, | |
174 const char *, unsigned long) = | |
175 0; | |
169 | 176 |
170 /* Define this to make dlcompat reuse data block. This way in theory we save | 177 /* Define this to make dlcompat reuse data block. This way in theory we save |
171 * a little bit of overhead. However we then couldn't correctly catch excess | 178 * a little bit of overhead. However we then couldn't correctly catch excess |
172 * calls to SDL_OSX_dlclose(). Hence we don't use this feature | 179 * calls to SDL_OSX_dlclose(). Hence we don't use this feature |
173 */ | 180 */ |
192 */ | 199 */ |
193 static pthread_key_t dlerror_key; | 200 static pthread_key_t dlerror_key; |
194 | 201 |
195 struct dlthread | 202 struct dlthread |
196 { | 203 { |
197 int lockcnt; | 204 int lockcnt; |
198 unsigned char errset; | 205 unsigned char errset; |
199 char errstr[ERR_STR_LEN]; | 206 char errstr[ERR_STR_LEN]; |
200 }; | 207 }; |
201 | 208 |
202 /* This is our central data structure. Whenever a module is loaded via | 209 /* This is our central data structure. Whenever a module is loaded via |
203 * SDL_OSX_dlopen(), we create such a struct. | 210 * SDL_OSX_dlopen(), we create such a struct. |
204 */ | 211 */ |
205 struct dlstatus | 212 struct dlstatus |
206 { | 213 { |
207 struct dlstatus *next; /* pointer to next element in the linked list */ | 214 struct dlstatus *next; /* pointer to next element in the linked list */ |
208 NSModule module; | 215 NSModule module; |
209 const struct mach_header *lib; | 216 const struct mach_header *lib; |
210 int refs; /* reference count */ | 217 int refs; /* reference count */ |
211 int mode; /* mode in which this module was loaded */ | 218 int mode; /* mode in which this module was loaded */ |
212 dev_t device; | 219 dev_t device; |
213 ino_t inode; | 220 ino_t inode; |
214 int flags; /* Any internal flags we may need */ | 221 int flags; /* Any internal flags we may need */ |
215 }; | 222 }; |
216 | 223 |
217 /* Head node of the dlstatus list */ | 224 /* Head node of the dlstatus list */ |
218 static struct dlstatus mainStatus = { 0, MAGIC_DYLIB_MOD, NULL, -1, RTLD_GLOBAL, 0, 0, 0 }; | 225 static struct dlstatus mainStatus = |
226 { 0, MAGIC_DYLIB_MOD, NULL, -1, RTLD_GLOBAL, 0, 0, 0 }; | |
219 static struct dlstatus *stqueue = &mainStatus; | 227 static struct dlstatus *stqueue = &mainStatus; |
220 | 228 |
221 | 229 |
222 /* Storage for the last error message (used by dlerror()) */ | 230 /* Storage for the last error message (used by dlerror()) */ |
223 /* static char err_str[ERR_STR_LEN]; */ | 231 /* static char err_str[ERR_STR_LEN]; */ |
224 /* static int err_filled = 0; */ | 232 /* static int err_filled = 0; */ |
225 | 233 |
226 /* Prototypes to internal functions */ | 234 /* Prototypes to internal functions */ |
227 static void debug(const char *fmt, ...); | 235 static void debug (const char *fmt, ...); |
228 static void error(const char *str, ...); | 236 static void error (const char *str, ...); |
229 static const char *safegetenv(const char *s); | 237 static const char *safegetenv (const char *s); |
230 static const char *searchList(void); | 238 static const char *searchList (void); |
231 static const char *getSearchPath(int i); | 239 static const char *getSearchPath (int i); |
232 static const char *getFullPath(int i, const char *file); | 240 static const char *getFullPath (int i, const char *file); |
233 static const struct stat *findFile(const char *file, const char **fullPath); | 241 static const struct stat *findFile (const char *file, const char **fullPath); |
234 static int isValidStatus(struct dlstatus *status); | 242 static int isValidStatus (struct dlstatus *status); |
235 static inline int isFlagSet(int mode, int flag); | 243 static inline int isFlagSet (int mode, int flag); |
236 static struct dlstatus *lookupStatus(const struct stat *sbuf); | 244 static struct dlstatus *lookupStatus (const struct stat *sbuf); |
237 static void insertStatus(struct dlstatus *dls, const struct stat *sbuf); | 245 static void insertStatus (struct dlstatus *dls, const struct stat *sbuf); |
238 static int promoteLocalToGlobal(struct dlstatus *dls); | 246 static int promoteLocalToGlobal (struct dlstatus *dls); |
239 static void *reference(struct dlstatus *dls, int mode); | 247 static void *reference (struct dlstatus *dls, int mode); |
240 static void *dlsymIntern(struct dlstatus *dls, const char *symbol, int canSetError); | 248 static void *dlsymIntern (struct dlstatus *dls, const char *symbol, |
241 static struct dlstatus *allocStatus(void); | 249 int canSetError); |
242 static struct dlstatus *loadModule(const char *path, const struct stat *sbuf, int mode); | 250 static struct dlstatus *allocStatus (void); |
243 static NSSymbol search_linked_libs(const struct mach_header *mh, const char *symbol); | 251 static struct dlstatus *loadModule (const char *path, const struct stat *sbuf, |
244 static const char *get_lib_name(const struct mach_header *mh); | 252 int mode); |
245 static const struct mach_header *get_mach_header_from_NSModule(NSModule mod); | 253 static NSSymbol search_linked_libs (const struct mach_header *mh, |
246 static void dlcompat_init_func(void); | 254 const char *symbol); |
247 static inline void dlcompat_init_check(void); | 255 static const char *get_lib_name (const struct mach_header *mh); |
248 static inline void dolock(void); | 256 static const struct mach_header *get_mach_header_from_NSModule (NSModule mod); |
249 static inline void dounlock(void); | 257 static void dlcompat_init_func (void); |
250 static void dlerrorfree(void *data); | 258 static inline void dlcompat_init_check (void); |
251 static void resetdlerror(void); | 259 static inline void dolock (void); |
252 static const struct mach_header *my_find_image(const char *name); | 260 static inline void dounlock (void); |
253 static const struct mach_header *image_for_address(const void *address); | 261 static void dlerrorfree (void *data); |
254 static inline char *dyld_error_str(void); | 262 static void resetdlerror (void); |
263 static const struct mach_header *my_find_image (const char *name); | |
264 static const struct mach_header *image_for_address (const void *address); | |
265 static inline char *dyld_error_str (void); | |
255 | 266 |
256 #if FINK_BUILD | 267 #if FINK_BUILD |
257 /* Two Global Functions */ | 268 /* Two Global Functions */ |
258 static void *dlsym_prepend_underscore(void *handle, const char *symbol); | 269 static void *dlsym_prepend_underscore (void *handle, const char *symbol); |
259 static void *dlsym_auto_underscore(void *handle, const char *symbol); | 270 static void *dlsym_auto_underscore (void *handle, const char *symbol); |
260 | 271 |
261 /* And their _intern counterparts */ | 272 /* And their _intern counterparts */ |
262 static void *dlsym_prepend_underscore_intern(void *handle, const char *symbol); | 273 static void *dlsym_prepend_underscore_intern (void *handle, |
263 static void *dlsym_auto_underscore_intern(void *handle, const char *symbol); | 274 const char *symbol); |
275 static void *dlsym_auto_underscore_intern (void *handle, const char *symbol); | |
264 #endif | 276 #endif |
265 | 277 |
266 /* Functions */ | 278 /* Functions */ |
267 | 279 |
268 static void debug(const char *fmt, ...) | 280 static void |
281 debug (const char *fmt, ...) | |
269 { | 282 { |
270 #if DEBUG > 1 | 283 #if DEBUG > 1 |
271 va_list arg; | 284 va_list arg; |
272 va_start(arg, fmt); | 285 va_start (arg, fmt); |
273 fprintf(stderr, "DLDEBUG: "); | 286 fprintf (stderr, "DLDEBUG: "); |
274 vfprintf(stderr, fmt, arg); | 287 vfprintf (stderr, fmt, arg); |
275 fprintf(stderr, "\n"); | 288 fprintf (stderr, "\n"); |
276 fflush(stderr); | 289 fflush (stderr); |
277 va_end(arg); | 290 va_end (arg); |
278 #endif | 291 #endif |
279 } | 292 } |
280 | 293 |
281 static void error(const char *str, ...) | 294 static void |
282 { | 295 error (const char *str, ...) |
283 va_list arg; | 296 { |
284 struct dlthread *tss; | 297 va_list arg; |
285 char * err_str; | 298 struct dlthread *tss; |
286 va_start(arg, str); | 299 char *err_str; |
287 tss = pthread_getspecific(dlerror_key); | 300 va_start (arg, str); |
288 err_str = tss->errstr; | 301 tss = pthread_getspecific (dlerror_key); |
289 SDL_strlcpy(err_str, "dlcompat: ", ERR_STR_LEN); | 302 err_str = tss->errstr; |
290 vsnprintf(err_str + 10, ERR_STR_LEN - 10, str, arg); | 303 SDL_strlcpy (err_str, "dlcompat: ", ERR_STR_LEN); |
291 va_end(arg); | 304 vsnprintf (err_str + 10, ERR_STR_LEN - 10, str, arg); |
292 debug("ERROR: %s\n", err_str); | 305 va_end (arg); |
293 tss->errset = 1; | 306 debug ("ERROR: %s\n", err_str); |
294 } | 307 tss->errset = 1; |
295 | 308 } |
296 static void warning(const char *str) | 309 |
310 static void | |
311 warning (const char *str) | |
297 { | 312 { |
298 #if DEBUG > 0 | 313 #if DEBUG > 0 |
299 fprintf(stderr, "WARNING: dlcompat: %s\n", str); | 314 fprintf (stderr, "WARNING: dlcompat: %s\n", str); |
300 #endif | 315 #endif |
301 } | 316 } |
302 | 317 |
303 static const char *safegetenv(const char *s) | 318 static const char * |
304 { | 319 safegetenv (const char *s) |
305 const char *ss = SDL_getenv(s); | 320 { |
306 return ss ? ss : ""; | 321 const char *ss = SDL_getenv (s); |
322 return ss ? ss : ""; | |
307 } | 323 } |
308 | 324 |
309 /* because this is only used for debugging and error reporting functions, we | 325 /* because this is only used for debugging and error reporting functions, we |
310 * don't really care about how elegant it is... it could use the load | 326 * don't really care about how elegant it is... it could use the load |
311 * commands to find the install name of the library, but... | 327 * commands to find the install name of the library, but... |
312 */ | 328 */ |
313 static const char *get_lib_name(const struct mach_header *mh) | 329 static const char * |
314 { | 330 get_lib_name (const struct mach_header *mh) |
315 unsigned long count = _dyld_image_count(); | 331 { |
316 unsigned long i; | 332 unsigned long count = _dyld_image_count (); |
317 const char *val = NULL; | 333 unsigned long i; |
318 if (mh) | 334 const char *val = NULL; |
319 { | 335 if (mh) { |
320 for (i = 0; i < count; i++) | 336 for (i = 0; i < count; i++) { |
321 { | 337 if (mh == _dyld_get_image_header (i)) { |
322 if (mh == _dyld_get_image_header(i)) | 338 val = _dyld_get_image_name (i); |
323 { | 339 break; |
324 val = _dyld_get_image_name(i); | 340 } |
325 break; | 341 } |
326 } | 342 } |
327 } | 343 return val; |
328 } | |
329 return val; | |
330 } | 344 } |
331 | 345 |
332 /* Returns the mach_header for the module bu going through all the loaded images | 346 /* Returns the mach_header for the module bu going through all the loaded images |
333 * and finding the one with the same name as the module. There really ought to be | 347 * and finding the one with the same name as the module. There really ought to be |
334 * an api for doing this, would be faster, but there isn't one right now | 348 * an api for doing this, would be faster, but there isn't one right now |
335 */ | 349 */ |
336 static const struct mach_header *get_mach_header_from_NSModule(NSModule mod) | 350 static const struct mach_header * |
337 { | 351 get_mach_header_from_NSModule (NSModule mod) |
338 const char *mod_name = NSNameOfModule(mod); | 352 { |
339 const struct mach_header *mh = NULL; | 353 const char *mod_name = NSNameOfModule (mod); |
340 unsigned long count = _dyld_image_count(); | 354 const struct mach_header *mh = NULL; |
341 unsigned long i; | 355 unsigned long count = _dyld_image_count (); |
342 debug("Module name: %s", mod_name); | 356 unsigned long i; |
343 for (i = 0; i < count; i++) | 357 debug ("Module name: %s", mod_name); |
344 { | 358 for (i = 0; i < count; i++) { |
345 if (!SDL_strcmp(mod_name, _dyld_get_image_name(i))) | 359 if (!SDL_strcmp (mod_name, _dyld_get_image_name (i))) { |
346 { | 360 mh = _dyld_get_image_header (i); |
347 mh = _dyld_get_image_header(i); | 361 break; |
348 break; | 362 } |
349 } | 363 } |
350 } | 364 return mh; |
351 return mh; | |
352 } | 365 } |
353 | 366 |
354 | 367 |
355 /* Compute and return a list of all directories that we should search when | 368 /* Compute and return a list of all directories that we should search when |
356 * trying to locate a module. We first look at the values of LD_LIBRARY_PATH | 369 * trying to locate a module. We first look at the values of LD_LIBRARY_PATH |
358 * /usr/lib and /lib. Since both of the environments variables can contain a | 371 * /usr/lib and /lib. Since both of the environments variables can contain a |
359 * list of colon seperated paths, we simply concat them and the two other paths | 372 * list of colon seperated paths, we simply concat them and the two other paths |
360 * into one big string, which we then can easily parse. | 373 * into one big string, which we then can easily parse. |
361 * Splitting this string into the actual path list is done by getSearchPath() | 374 * Splitting this string into the actual path list is done by getSearchPath() |
362 */ | 375 */ |
363 static const char *searchList() | 376 static const char * |
364 { | 377 searchList () |
365 size_t buf_size; | 378 { |
366 static char *buf=NULL; | 379 size_t buf_size; |
367 const char *ldlp = safegetenv("LD_LIBRARY_PATH"); | 380 static char *buf = NULL; |
368 const char *dyldlp = safegetenv("DYLD_LIBRARY_PATH"); | 381 const char *ldlp = safegetenv ("LD_LIBRARY_PATH"); |
369 const char *stdpath = SDL_getenv("DYLD_FALLBACK_LIBRARY_PATH"); | 382 const char *dyldlp = safegetenv ("DYLD_LIBRARY_PATH"); |
370 if (!stdpath) | 383 const char *stdpath = SDL_getenv ("DYLD_FALLBACK_LIBRARY_PATH"); |
371 stdpath = "/usr/local/lib:/lib:/usr/lib"; | 384 if (!stdpath) |
372 if (!buf) | 385 stdpath = "/usr/local/lib:/lib:/usr/lib"; |
373 { | 386 if (!buf) { |
374 buf_size = SDL_strlen(ldlp) + SDL_strlen(dyldlp) + SDL_strlen(stdpath) + 4; | 387 buf_size = |
375 buf = SDL_malloc(buf_size); | 388 SDL_strlen (ldlp) + SDL_strlen (dyldlp) + SDL_strlen (stdpath) + |
376 SDL_snprintf(buf, buf_size, "%s%s%s%s%s%c", dyldlp, (dyldlp[0] ? ":" : ""), ldlp, (ldlp[0] ? ":" : ""), | 389 4; |
377 stdpath, '\0'); | 390 buf = SDL_malloc (buf_size); |
378 } | 391 SDL_snprintf (buf, buf_size, "%s%s%s%s%s%c", dyldlp, |
379 return buf; | 392 (dyldlp[0] ? ":" : ""), ldlp, (ldlp[0] ? ":" : ""), |
393 stdpath, '\0'); | |
394 } | |
395 return buf; | |
380 } | 396 } |
381 | 397 |
382 /* Returns the ith search path from the list as computed by searchList() */ | 398 /* Returns the ith search path from the list as computed by searchList() */ |
383 static const char *getSearchPath(int i) | 399 static const char * |
384 { | 400 getSearchPath (int i) |
385 static const char *list = 0; | 401 { |
386 static char **path = (char **)0; | 402 static const char *list = 0; |
387 static int end = 0; | 403 static char **path = (char **) 0; |
388 static int numsize = MAX_SEARCH_PATHS; | 404 static int end = 0; |
389 static char **tmp; | 405 static int numsize = MAX_SEARCH_PATHS; |
390 /* So we can call SDL_free() in the "destructor" we use i=-1 to return the alloc'd array */ | 406 static char **tmp; |
391 if (i == -1) | 407 /* So we can call SDL_free() in the "destructor" we use i=-1 to return the alloc'd array */ |
392 { | 408 if (i == -1) { |
393 return (const char*)path; | 409 return (const char *) path; |
394 } | 410 } |
395 if (!path) | 411 if (!path) { |
396 { | 412 path = (char **) SDL_calloc (MAX_SEARCH_PATHS, sizeof (char **)); |
397 path = (char **)SDL_calloc(MAX_SEARCH_PATHS, sizeof(char **)); | 413 } |
398 } | 414 if (!list && !end) |
399 if (!list && !end) | 415 list = searchList (); |
400 list = searchList(); | 416 if (i >= (numsize)) { |
401 if (i >= (numsize)) | 417 debug ("Increasing size for long PATH"); |
402 { | 418 tmp = |
403 debug("Increasing size for long PATH"); | 419 (char **) SDL_calloc ((MAX_SEARCH_PATHS + numsize), |
404 tmp = (char **)SDL_calloc((MAX_SEARCH_PATHS + numsize), sizeof(char **)); | 420 sizeof (char **)); |
405 if (tmp) | 421 if (tmp) { |
406 { | 422 SDL_memcpy (tmp, path, sizeof (char **) * numsize); |
407 SDL_memcpy(tmp, path, sizeof(char **) * numsize); | 423 SDL_free (path); |
408 SDL_free(path); | 424 path = tmp; |
409 path = tmp; | 425 numsize += MAX_SEARCH_PATHS; |
410 numsize += MAX_SEARCH_PATHS; | 426 } else { |
411 } | 427 return 0; |
412 else | 428 } |
413 { | 429 } |
414 return 0; | 430 |
415 } | 431 while (!path[i] && !end) { |
416 } | 432 path[i] = strsep ((char **) &list, ":"); |
417 | 433 |
418 while (!path[i] && !end) | 434 if (path[i][0] == 0) |
419 { | 435 path[i] = 0; |
420 path[i] = strsep((char **)&list, ":"); | 436 end = (list == 0); |
421 | 437 } |
422 if (path[i][0] == 0) | 438 return path[i]; |
423 path[i] = 0; | 439 } |
424 end = (list == 0); | 440 |
425 } | 441 static const char * |
426 return path[i]; | 442 getFullPath (int i, const char *file) |
427 } | 443 { |
428 | 444 static char buf[PATH_MAX]; |
429 static const char *getFullPath(int i, const char *file) | 445 const char *path = getSearchPath (i); |
430 { | 446 if (path) { |
431 static char buf[PATH_MAX]; | 447 SDL_snprintf (buf, PATH_MAX, "%s/%s", path, file); |
432 const char *path = getSearchPath(i); | 448 } |
433 if (path) | 449 return path ? buf : 0; |
434 { | |
435 SDL_snprintf(buf, PATH_MAX, "%s/%s", path, file); | |
436 } | |
437 return path ? buf : 0; | |
438 } | 450 } |
439 | 451 |
440 /* Given a file name, try to determine the full path for that file. Starts | 452 /* Given a file name, try to determine the full path for that file. Starts |
441 * its search in the current directory, and then tries all paths in the | 453 * its search in the current directory, and then tries all paths in the |
442 * search list in the order they are specified there. | 454 * search list in the order they are specified there. |
443 */ | 455 */ |
444 static const struct stat *findFile(const char *file, const char **fullPath) | 456 static const struct stat * |
445 { | 457 findFile (const char *file, const char **fullPath) |
446 int i = 0; | 458 { |
447 static struct stat sbuf; | 459 int i = 0; |
448 char *fileName; | 460 static struct stat sbuf; |
449 debug("finding file %s", file); | 461 char *fileName; |
450 *fullPath = file; | 462 debug ("finding file %s", file); |
451 if (0 == stat(file, &sbuf)) | 463 *fullPath = file; |
452 return &sbuf; | 464 if (0 == stat (file, &sbuf)) |
453 if (SDL_strchr(file, '/')) | 465 return &sbuf; |
454 return 0; /* If the path had a / we don't look in env var places */ | 466 if (SDL_strchr (file, '/')) |
455 fileName = NULL; | 467 return 0; /* If the path had a / we don't look in env var places */ |
456 if (!fileName) | 468 fileName = NULL; |
457 fileName = (char *)file; | 469 if (!fileName) |
458 while ((*fullPath = getFullPath(i++, fileName))) | 470 fileName = (char *) file; |
459 { | 471 while ((*fullPath = getFullPath (i++, fileName))) { |
460 if (0 == stat(*fullPath, &sbuf)) | 472 if (0 == stat (*fullPath, &sbuf)) |
461 return &sbuf; | 473 return &sbuf; |
462 } | 474 } |
463 ; | 475 ; |
464 return 0; | 476 return 0; |
465 } | 477 } |
466 | 478 |
467 /* Determine whether a given dlstatus is valid or not */ | 479 /* Determine whether a given dlstatus is valid or not */ |
468 static int isValidStatus(struct dlstatus *status) | 480 static int |
469 { | 481 isValidStatus (struct dlstatus *status) |
470 /* Walk the list to verify status is contained in it */ | 482 { |
471 struct dlstatus *dls = stqueue; | 483 /* Walk the list to verify status is contained in it */ |
472 while (dls && status != dls) | 484 struct dlstatus *dls = stqueue; |
473 dls = dls->next; | 485 while (dls && status != dls) |
474 if (dls == 0) | 486 dls = dls->next; |
475 error("invalid handle"); | 487 if (dls == 0) |
476 else if ((dls->module == 0) || (dls->refs == 0)) | 488 error ("invalid handle"); |
477 error("handle to closed library"); | 489 else if ((dls->module == 0) || (dls->refs == 0)) |
478 else | 490 error ("handle to closed library"); |
479 return TRUE; | 491 else |
480 return FALSE; | 492 return TRUE; |
481 } | 493 return FALSE; |
482 | 494 } |
483 static inline int isFlagSet(int mode, int flag) | 495 |
484 { | 496 static inline int |
485 return (mode & flag) == flag; | 497 isFlagSet (int mode, int flag) |
486 } | 498 { |
487 | 499 return (mode & flag) == flag; |
488 static struct dlstatus *lookupStatus(const struct stat *sbuf) | 500 } |
489 { | 501 |
490 struct dlstatus *dls = stqueue; | 502 static struct dlstatus * |
491 debug("looking for status"); | 503 lookupStatus (const struct stat *sbuf) |
492 while (dls && ( /* isFlagSet(dls->mode, RTLD_UNSHARED) */ 0 | 504 { |
493 || sbuf->st_dev != dls->device || sbuf->st_ino != dls->inode)) | 505 struct dlstatus *dls = stqueue; |
494 dls = dls->next; | 506 debug ("looking for status"); |
495 return dls; | 507 while (dls && ( /* isFlagSet(dls->mode, RTLD_UNSHARED) */ 0 |
496 } | 508 || sbuf->st_dev != dls->device |
497 | 509 || sbuf->st_ino != dls->inode)) |
498 static void insertStatus(struct dlstatus *dls, const struct stat *sbuf) | 510 dls = dls->next; |
499 { | 511 return dls; |
500 debug("inserting status"); | 512 } |
501 dls->inode = sbuf->st_ino; | 513 |
502 dls->device = sbuf->st_dev; | 514 static void |
503 dls->refs = 0; | 515 insertStatus (struct dlstatus *dls, const struct stat *sbuf) |
504 dls->mode = 0; | 516 { |
505 if ((dls->flags & DL_IN_LIST) == 0) | 517 debug ("inserting status"); |
506 { | 518 dls->inode = sbuf->st_ino; |
507 dls->next = stqueue; | 519 dls->device = sbuf->st_dev; |
508 stqueue = dls; | 520 dls->refs = 0; |
509 dls->flags |= DL_IN_LIST; | 521 dls->mode = 0; |
510 } | 522 if ((dls->flags & DL_IN_LIST) == 0) { |
511 } | 523 dls->next = stqueue; |
512 | 524 stqueue = dls; |
513 static struct dlstatus *allocStatus() | 525 dls->flags |= DL_IN_LIST; |
514 { | 526 } |
515 struct dlstatus *dls; | 527 } |
528 | |
529 static struct dlstatus * | |
530 allocStatus () | |
531 { | |
532 struct dlstatus *dls; | |
516 #ifdef REUSE_STATUS | 533 #ifdef REUSE_STATUS |
517 dls = stqueue; | 534 dls = stqueue; |
518 while (dls && dls->module) | 535 while (dls && dls->module) |
519 dls = dls->next; | 536 dls = dls->next; |
520 if (!dls) | 537 if (!dls) |
521 #endif | 538 #endif |
522 dls = SDL_calloc(sizeof(*dls),1); | 539 dls = SDL_calloc (sizeof (*dls), 1); |
523 return dls; | 540 return dls; |
524 } | 541 } |
525 | 542 |
526 static int promoteLocalToGlobal(struct dlstatus *dls) | 543 static int |
527 { | 544 promoteLocalToGlobal (struct dlstatus *dls) |
528 static int (*p) (NSModule module) = 0; | 545 { |
529 debug("promoting"); | 546 static int (*p) (NSModule module) = 0; |
530 if (!p) | 547 debug ("promoting"); |
531 _dyld_func_lookup("__dyld_NSMakePrivateModulePublic", (void **)&p); | 548 if (!p) |
532 return (dls->module == MAGIC_DYLIB_MOD) || (p && p(dls->module)); | 549 _dyld_func_lookup ("__dyld_NSMakePrivateModulePublic", (void **) &p); |
533 } | 550 return (dls->module == MAGIC_DYLIB_MOD) || (p && p (dls->module)); |
534 | 551 } |
535 static void *reference(struct dlstatus *dls, int mode) | 552 |
536 { | 553 static void * |
537 if (dls) | 554 reference (struct dlstatus *dls, int mode) |
538 { | 555 { |
539 if (dls->module == MAGIC_DYLIB_MOD && isFlagSet(mode, RTLD_LOCAL)) | 556 if (dls) { |
540 { | 557 if (dls->module == MAGIC_DYLIB_MOD && isFlagSet (mode, RTLD_LOCAL)) { |
541 warning("trying to open a .dylib with RTLD_LOCAL"); | 558 warning ("trying to open a .dylib with RTLD_LOCAL"); |
542 error("unable to open a .dylib with RTLD_LOCAL"); | 559 error ("unable to open a .dylib with RTLD_LOCAL"); |
543 return NULL; | 560 return NULL; |
544 } | 561 } |
545 if (isFlagSet(mode, RTLD_GLOBAL) && | 562 if (isFlagSet (mode, RTLD_GLOBAL) && |
546 !isFlagSet(dls->mode, RTLD_GLOBAL) && !promoteLocalToGlobal(dls)) | 563 !isFlagSet (dls->mode, RTLD_GLOBAL) |
547 { | 564 && !promoteLocalToGlobal (dls)) { |
548 error("unable to promote local module to global"); | 565 error ("unable to promote local module to global"); |
549 return NULL; | 566 return NULL; |
550 } | 567 } |
551 dls->mode |= mode; | 568 dls->mode |= mode; |
552 dls->refs++; | 569 dls->refs++; |
553 } | 570 } else |
554 else | 571 debug ("reference called with NULL argument"); |
555 debug("reference called with NULL argument"); | 572 |
556 | 573 return dls; |
557 return dls; | 574 } |
558 } | 575 |
559 | 576 static const struct mach_header * |
560 static const struct mach_header *my_find_image(const char *name) | 577 my_find_image (const char *name) |
561 { | 578 { |
562 const struct mach_header *mh = 0; | 579 const struct mach_header *mh = 0; |
563 const char *id = NULL; | 580 const char *id = NULL; |
564 int i = _dyld_image_count(); | 581 int i = _dyld_image_count (); |
565 int j; | 582 int j; |
566 mh = (struct mach_header *) | 583 mh = (struct mach_header *) |
567 dyld_NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED | | 584 dyld_NSAddImage (name, NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED | |
568 NSADDIMAGE_OPTION_RETURN_ON_ERROR); | 585 NSADDIMAGE_OPTION_RETURN_ON_ERROR); |
569 if (!mh) | 586 if (!mh) { |
570 { | 587 for (j = 0; j < i; j++) { |
571 for (j = 0; j < i; j++) | 588 id = _dyld_get_image_name (j); |
572 { | 589 if (!SDL_strcmp (id, name)) { |
573 id = _dyld_get_image_name(j); | 590 mh = _dyld_get_image_header (j); |
574 if (!SDL_strcmp(id, name)) | 591 break; |
575 { | 592 } |
576 mh = _dyld_get_image_header(j); | 593 } |
577 break; | 594 } |
578 } | 595 return mh; |
579 } | |
580 } | |
581 return mh; | |
582 } | 596 } |
583 | 597 |
584 /* | 598 /* |
585 * dyld adds libraries by first adding the directly dependant libraries in link order, and | 599 * dyld adds libraries by first adding the directly dependant libraries in link order, and |
586 * then adding the dependencies for those libraries, so we should do the same... but we don't | 600 * then adding the dependencies for those libraries, so we should do the same... but we don't |
587 * bother adding the extra dependencies, if the symbols are neither in the loaded image nor | 601 * bother adding the extra dependencies, if the symbols are neither in the loaded image nor |
588 * any of it's direct dependencies, then it probably isn't there. | 602 * any of it's direct dependencies, then it probably isn't there. |
589 */ | 603 */ |
590 static NSSymbol search_linked_libs(const struct mach_header * mh, const char *symbol) | 604 static NSSymbol |
591 { | 605 search_linked_libs (const struct mach_header *mh, const char *symbol) |
592 unsigned int n; | 606 { |
593 struct load_command *lc = 0; | 607 unsigned int n; |
594 struct mach_header *wh; | 608 struct load_command *lc = 0; |
595 NSSymbol nssym = 0; | 609 struct mach_header *wh; |
596 if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage) | 610 NSSymbol nssym = 0; |
597 { | 611 if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage |
598 lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); | 612 && dyld_NSLookupSymbolInImage) { |
599 for (n = 0; n < mh->ncmds; n++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) | 613 lc = (struct load_command *) ((char *) mh + |
600 { | 614 sizeof (struct mach_header)); |
601 if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd)) | 615 for (n = 0; n < mh->ncmds; |
602 { | 616 n++, lc = (struct load_command *) ((char *) lc + lc->cmdsize)) { |
603 if ((wh = (struct mach_header *) | 617 if ((LC_LOAD_DYLIB == lc->cmd) |
604 my_find_image((char *)(((struct dylib_command *)lc)->dylib.name.offset + | 618 || (LC_LOAD_WEAK_DYLIB == lc->cmd)) { |
605 (char *)lc)))) | 619 if ((wh = (struct mach_header *) |
606 { | 620 my_find_image ((char |
607 if (dyld_NSIsSymbolNameDefinedInImage(wh, symbol)) | 621 *) (((struct dylib_command *) lc)-> |
608 { | 622 dylib.name.offset + (char *) lc)))) { |
609 nssym = dyld_NSLookupSymbolInImage(wh, | 623 if (dyld_NSIsSymbolNameDefinedInImage (wh, symbol)) { |
610 symbol, | 624 nssym = dyld_NSLookupSymbolInImage (wh, |
611 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | | 625 symbol, |
612 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); | 626 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
613 break; | 627 | |
614 } | 628 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); |
615 } | 629 break; |
616 } | 630 } |
617 } | 631 } |
618 if ((!nssym) && NSIsSymbolNameDefined(symbol)) | 632 } |
619 { | 633 } |
620 /* I've never seen this debug message...*/ | 634 if ((!nssym) && NSIsSymbolNameDefined (symbol)) { |
621 debug("Symbol \"%s\" is defined but was not found", symbol); | 635 /* I've never seen this debug message... */ |
622 } | 636 debug ("Symbol \"%s\" is defined but was not found", symbol); |
623 } | 637 } |
624 return nssym; | 638 } |
639 return nssym; | |
625 } | 640 } |
626 | 641 |
627 /* Up to the caller to SDL_free() returned string */ | 642 /* Up to the caller to SDL_free() returned string */ |
628 static inline char *dyld_error_str() | 643 static inline char * |
629 { | 644 dyld_error_str () |
630 NSLinkEditErrors dylder; | 645 { |
631 int dylderno; | 646 NSLinkEditErrors dylder; |
632 const char *dylderrstr; | 647 int dylderno; |
633 const char *dyldfile; | 648 const char *dylderrstr; |
634 char* retStr = NULL; | 649 const char *dyldfile; |
635 NSLinkEditError(&dylder, &dylderno, &dyldfile, &dylderrstr); | 650 char *retStr = NULL; |
636 if (dylderrstr && *dylderrstr) | 651 NSLinkEditError (&dylder, &dylderno, &dyldfile, &dylderrstr); |
637 { | 652 if (dylderrstr && *dylderrstr) { |
638 retStr = SDL_strdup(dylderrstr); | 653 retStr = SDL_strdup (dylderrstr); |
639 } | 654 } |
640 return retStr; | 655 return retStr; |
641 } | 656 } |
642 | 657 |
643 static void *dlsymIntern(struct dlstatus *dls, const char *symbol, int canSetError) | 658 static void * |
644 { | 659 dlsymIntern (struct dlstatus *dls, const char *symbol, int canSetError) |
645 NSSymbol nssym = 0; | 660 { |
646 #ifdef __GCC__ | 661 NSSymbol nssym = 0; |
647 void *caller = __builtin_return_address(1); /* Be *very* careful about inlining */ | 662 #ifdef __GCC__ |
663 void *caller = __builtin_return_address (1); /* Be *very* careful about inlining */ | |
648 #else | 664 #else |
649 void *caller = NULL; | 665 void *caller = NULL; |
650 #endif | 666 #endif |
651 const struct mach_header *caller_mh = 0; | 667 const struct mach_header *caller_mh = 0; |
652 char *savedErrorStr = NULL; | 668 char *savedErrorStr = NULL; |
653 resetdlerror(); | 669 resetdlerror (); |
654 #ifndef RTLD_SELF | 670 #ifndef RTLD_SELF |
655 #define RTLD_SELF ((void *) -3) | 671 #define RTLD_SELF ((void *) -3) |
656 #endif | 672 #endif |
657 if (NULL == dls) | 673 if (NULL == dls) |
658 dls = RTLD_SELF; | 674 dls = RTLD_SELF; |
659 if ((RTLD_NEXT == dls) || (RTLD_SELF == dls)) | 675 if ((RTLD_NEXT == dls) || (RTLD_SELF == dls)) { |
660 { | 676 if (dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage |
661 if (dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage && caller) | 677 && caller) { |
662 { | 678 caller_mh = image_for_address (caller); |
663 caller_mh = image_for_address(caller); | 679 if (RTLD_SELF == dls) { |
664 if (RTLD_SELF == dls) | 680 /* FIXME: We should be using the NSModule api, if SELF is an MH_BUNDLE |
665 { | 681 * But it appears to work anyway, and looking at the code in dyld_libfuncs.c |
666 /* FIXME: We should be using the NSModule api, if SELF is an MH_BUNDLE | 682 * this is acceptable. |
667 * But it appears to work anyway, and looking at the code in dyld_libfuncs.c | 683 */ |
668 * this is acceptable. | 684 if (dyld_NSIsSymbolNameDefinedInImage (caller_mh, symbol)) { |
669 */ | 685 nssym = dyld_NSLookupSymbolInImage (caller_mh, |
670 if (dyld_NSIsSymbolNameDefinedInImage(caller_mh, symbol)) | 686 symbol, |
671 { | 687 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
672 nssym = dyld_NSLookupSymbolInImage(caller_mh, | 688 | |
673 symbol, | 689 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); |
674 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | | 690 } |
675 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); | 691 } |
676 } | 692 if (!nssym) { |
677 } | 693 if (RTLD_SELF == dls) |
678 if (!nssym) | 694 savedErrorStr = dyld_error_str (); |
679 { | 695 nssym = search_linked_libs (caller_mh, symbol); |
680 if (RTLD_SELF == dls) | 696 } |
681 savedErrorStr = dyld_error_str(); | 697 } else { |
682 nssym = search_linked_libs(caller_mh, symbol); | 698 if (canSetError) |
683 } | 699 error ("RTLD_SELF and RTLD_NEXT are not supported"); |
684 } | 700 return NULL; |
685 else | 701 } |
686 { | 702 } |
687 if (canSetError) | 703 if (!nssym) { |
688 error("RTLD_SELF and RTLD_NEXT are not supported"); | 704 |
689 return NULL; | 705 if (RTLD_DEFAULT == dls) { |
690 } | 706 dls = &mainStatus; |
691 } | 707 } |
692 if (!nssym) | 708 if (!isValidStatus (dls)) |
693 { | 709 return NULL; |
694 | 710 |
695 if (RTLD_DEFAULT == dls) | 711 if (dls->module != MAGIC_DYLIB_MOD) { |
696 { | 712 nssym = NSLookupSymbolInModule (dls->module, symbol); |
697 dls = &mainStatus; | 713 if (!nssym && NSIsSymbolNameDefined (symbol)) { |
698 } | 714 debug ("Searching dependencies"); |
699 if (!isValidStatus(dls)) | 715 savedErrorStr = dyld_error_str (); |
700 return NULL; | 716 nssym = |
701 | 717 search_linked_libs (get_mach_header_from_NSModule |
702 if (dls->module != MAGIC_DYLIB_MOD) | 718 (dls->module), symbol); |
703 { | 719 } |
704 nssym = NSLookupSymbolInModule(dls->module, symbol); | 720 } else if (dls->lib && dyld_NSIsSymbolNameDefinedInImage |
705 if (!nssym && NSIsSymbolNameDefined(symbol)) | 721 && dyld_NSLookupSymbolInImage) { |
706 { | 722 if (dyld_NSIsSymbolNameDefinedInImage (dls->lib, symbol)) { |
707 debug("Searching dependencies"); | 723 nssym = dyld_NSLookupSymbolInImage (dls->lib, |
708 savedErrorStr = dyld_error_str(); | 724 symbol, |
709 nssym = search_linked_libs(get_mach_header_from_NSModule(dls->module), symbol); | 725 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND |
710 } | 726 | |
711 } | 727 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); |
712 else if (dls->lib && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage) | 728 } else if (NSIsSymbolNameDefined (symbol)) { |
713 { | 729 debug ("Searching dependencies"); |
714 if (dyld_NSIsSymbolNameDefinedInImage(dls->lib, symbol)) | 730 savedErrorStr = dyld_error_str (); |
715 { | 731 nssym = search_linked_libs (dls->lib, symbol); |
716 nssym = dyld_NSLookupSymbolInImage(dls->lib, | 732 } |
717 symbol, | 733 } else if (dls->module == MAGIC_DYLIB_MOD) { |
718 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | | 734 /* Global context, use NSLookupAndBindSymbol */ |
719 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); | 735 if (NSIsSymbolNameDefined (symbol)) { |
720 } | 736 /* There doesn't seem to be a return on error option for this call??? |
721 else if (NSIsSymbolNameDefined(symbol)) | 737 this is potentially broken, if binding fails, it will improperly |
722 { | 738 exit the application. */ |
723 debug("Searching dependencies"); | 739 nssym = NSLookupAndBindSymbol (symbol); |
724 savedErrorStr = dyld_error_str(); | 740 } else { |
725 nssym = search_linked_libs(dls->lib, symbol); | 741 if (savedErrorStr) |
726 } | 742 SDL_free (savedErrorStr); |
727 } | 743 savedErrorStr = SDL_malloc (256); |
728 else if (dls->module == MAGIC_DYLIB_MOD) | 744 SDL_snprintf (savedErrorStr, 256, |
729 { | 745 "Symbol \"%s\" not in global context", symbol); |
730 /* Global context, use NSLookupAndBindSymbol */ | 746 } |
731 if (NSIsSymbolNameDefined(symbol)) | 747 } |
732 { | 748 } |
733 /* There doesn't seem to be a return on error option for this call??? | 749 /* Error reporting */ |
734 this is potentially broken, if binding fails, it will improperly | 750 if (!nssym) { |
735 exit the application. */ | 751 if (!savedErrorStr || !SDL_strlen (savedErrorStr)) { |
736 nssym = NSLookupAndBindSymbol(symbol); | 752 if (savedErrorStr) |
737 } | 753 SDL_free (savedErrorStr); |
738 else | 754 savedErrorStr = SDL_malloc (256); |
739 { | 755 SDL_snprintf (savedErrorStr, 256, "Symbol \"%s\" not found", |
740 if (savedErrorStr) | 756 symbol); |
741 SDL_free(savedErrorStr); | 757 } |
742 savedErrorStr = SDL_malloc(256); | 758 if (canSetError) { |
743 SDL_snprintf(savedErrorStr, 256, "Symbol \"%s\" not in global context",symbol); | 759 error (savedErrorStr); |
744 } | 760 } else { |
745 } | 761 debug (savedErrorStr); |
746 } | 762 } |
747 /* Error reporting */ | 763 if (savedErrorStr) |
748 if (!nssym) | 764 SDL_free (savedErrorStr); |
749 { | 765 return NULL; |
750 if (!savedErrorStr || !SDL_strlen(savedErrorStr)) | 766 } |
751 { | 767 return NSAddressOfSymbol (nssym); |
752 if (savedErrorStr) | 768 } |
753 SDL_free(savedErrorStr); | 769 |
754 savedErrorStr = SDL_malloc(256); | 770 static struct dlstatus * |
755 SDL_snprintf(savedErrorStr, 256,"Symbol \"%s\" not found",symbol); | 771 loadModule (const char *path, const struct stat *sbuf, int mode) |
756 } | 772 { |
757 if (canSetError) | 773 NSObjectFileImage ofi = 0; |
758 { | 774 NSObjectFileImageReturnCode ofirc; |
759 error(savedErrorStr); | 775 struct dlstatus *dls; |
760 } | 776 NSLinkEditErrors ler; |
761 else | 777 int lerno; |
762 { | 778 const char *errstr; |
763 debug(savedErrorStr); | 779 const char *file; |
764 } | 780 void (*init) (void); |
765 if (savedErrorStr) | 781 |
766 SDL_free(savedErrorStr); | 782 ofirc = NSCreateObjectFileImageFromFile (path, &ofi); |
767 return NULL; | 783 switch (ofirc) { |
768 } | 784 case NSObjectFileImageSuccess: |
769 return NSAddressOfSymbol(nssym); | 785 break; |
770 } | 786 case NSObjectFileImageInappropriateFile: |
771 | 787 if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage |
772 static struct dlstatus *loadModule(const char *path, const struct stat *sbuf, int mode) | 788 && dyld_NSLookupSymbolInImage) { |
773 { | 789 if (isFlagSet (mode, RTLD_LOCAL)) { |
774 NSObjectFileImage ofi = 0; | 790 warning ("trying to open a .dylib with RTLD_LOCAL"); |
775 NSObjectFileImageReturnCode ofirc; | 791 error ("unable to open this file with RTLD_LOCAL"); |
776 struct dlstatus *dls; | 792 return NULL; |
777 NSLinkEditErrors ler; | 793 } |
778 int lerno; | 794 } else { |
779 const char *errstr; | 795 error ("opening this file is unsupported on this system"); |
780 const char *file; | 796 return NULL; |
781 void (*init) (void); | 797 } |
782 | 798 break; |
783 ofirc = NSCreateObjectFileImageFromFile(path, &ofi); | 799 case NSObjectFileImageFailure: |
784 switch (ofirc) | 800 error ("object file setup failure"); |
785 { | 801 return NULL; |
786 case NSObjectFileImageSuccess: | 802 case NSObjectFileImageArch: |
787 break; | 803 error ("no object for this architecture"); |
788 case NSObjectFileImageInappropriateFile: | 804 return NULL; |
789 if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage) | 805 case NSObjectFileImageFormat: |
790 { | 806 error ("bad object file format"); |
791 if (isFlagSet(mode, RTLD_LOCAL)) | 807 return NULL; |
792 { | 808 case NSObjectFileImageAccess: |
793 warning("trying to open a .dylib with RTLD_LOCAL"); | 809 error ("can't read object file"); |
794 error("unable to open this file with RTLD_LOCAL"); | 810 return NULL; |
795 return NULL; | 811 default: |
796 } | 812 error ("unknown error from NSCreateObjectFileImageFromFile()"); |
797 } | 813 return NULL; |
798 else | 814 } |
799 { | 815 dls = lookupStatus (sbuf); |
800 error("opening this file is unsupported on this system"); | 816 if (!dls) { |
801 return NULL; | 817 dls = allocStatus (); |
802 } | 818 } |
803 break; | 819 if (!dls) { |
804 case NSObjectFileImageFailure: | 820 error ("unable to allocate memory"); |
805 error("object file setup failure"); | 821 return NULL; |
806 return NULL; | 822 } |
807 case NSObjectFileImageArch: | 823 // dls->lib = 0; |
808 error("no object for this architecture"); | 824 if (ofirc == NSObjectFileImageInappropriateFile) { |
809 return NULL; | 825 if ((dls->lib = |
810 case NSObjectFileImageFormat: | 826 dyld_NSAddImage (path, NSADDIMAGE_OPTION_RETURN_ON_ERROR))) { |
811 error("bad object file format"); | 827 debug ("Dynamic lib loaded at %ld", dls->lib); |
812 return NULL; | 828 ofi = MAGIC_DYLIB_OFI; |
813 case NSObjectFileImageAccess: | 829 dls->module = MAGIC_DYLIB_MOD; |
814 error("can't read object file"); | 830 ofirc = NSObjectFileImageSuccess; |
815 return NULL; | 831 /* Although it is possible with a bit of work to modify this so it works and |
816 default: | 832 functions with RTLD_NOW, I don't deem it necessary at the moment */ |
817 error("unknown error from NSCreateObjectFileImageFromFile()"); | 833 } |
818 return NULL; | 834 if (!(dls->module)) { |
819 } | 835 NSLinkEditError (&ler, &lerno, &file, &errstr); |
820 dls = lookupStatus(sbuf); | 836 if (!errstr || (!SDL_strlen (errstr))) |
821 if (!dls) | 837 error ("Can't open this file type"); |
822 { | 838 else |
823 dls = allocStatus(); | 839 error (errstr); |
824 } | 840 if ((dls->flags & DL_IN_LIST) == 0) { |
825 if (!dls) | 841 SDL_free (dls); |
826 { | 842 } |
827 error("unable to allocate memory"); | 843 return NULL; |
828 return NULL; | 844 } |
829 } | 845 } else { |
830 // dls->lib = 0; | 846 dls->module = NSLinkModule (ofi, path, |
831 if (ofirc == NSObjectFileImageInappropriateFile) | 847 NSLINKMODULE_OPTION_RETURN_ON_ERROR | |
832 { | 848 NSLINKMODULE_OPTION_PRIVATE | |
833 if ((dls->lib = dyld_NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR))) | 849 (isFlagSet (mode, RTLD_NOW) ? |
834 { | 850 NSLINKMODULE_OPTION_BINDNOW : 0)); |
835 debug("Dynamic lib loaded at %ld", dls->lib); | 851 NSDestroyObjectFileImage (ofi); |
836 ofi = MAGIC_DYLIB_OFI; | 852 if (dls->module) { |
837 dls->module = MAGIC_DYLIB_MOD; | 853 dls->lib = get_mach_header_from_NSModule (dls->module); |
838 ofirc = NSObjectFileImageSuccess; | 854 } |
839 /* Although it is possible with a bit of work to modify this so it works and | 855 } |
840 functions with RTLD_NOW, I don't deem it necessary at the moment */ | 856 if (!dls->module) { |
841 } | 857 NSLinkEditError (&ler, &lerno, &file, &errstr); |
842 if (!(dls->module)) | 858 if ((dls->flags & DL_IN_LIST) == 0) { |
843 { | 859 SDL_free (dls); |
844 NSLinkEditError(&ler, &lerno, &file, &errstr); | 860 } |
845 if (!errstr || (!SDL_strlen(errstr))) | 861 error (errstr); |
846 error("Can't open this file type"); | 862 return NULL; |
847 else | 863 } |
848 error(errstr); | 864 |
849 if ((dls->flags & DL_IN_LIST) == 0) | 865 insertStatus (dls, sbuf); |
850 { | 866 dls = reference (dls, mode); |
851 SDL_free(dls); | 867 if ((init = dlsymIntern (dls, "__init", 0))) { |
852 } | 868 debug ("calling _init()"); |
853 return NULL; | 869 init (); |
854 } | 870 } |
855 } | 871 return dls; |
856 else | 872 } |
857 { | 873 |
858 dls->module = NSLinkModule(ofi, path, | 874 inline static void |
859 NSLINKMODULE_OPTION_RETURN_ON_ERROR | | 875 dlcompat_init_check (void) |
860 NSLINKMODULE_OPTION_PRIVATE | | 876 { |
861 (isFlagSet(mode, RTLD_NOW) ? NSLINKMODULE_OPTION_BINDNOW : 0)); | 877 static pthread_mutex_t l = PTHREAD_MUTEX_INITIALIZER; |
862 NSDestroyObjectFileImage(ofi); | 878 static int init_done = 0; |
863 if (dls->module) | 879 |
864 { | 880 pthread_mutex_lock (&l); |
865 dls->lib = get_mach_header_from_NSModule(dls->module); | 881 if (!init_done) { |
866 } | 882 dlcompat_init_func (); |
867 } | 883 init_done = 1; |
868 if (!dls->module) | 884 } |
869 { | 885 pthread_mutex_unlock (&l); |
870 NSLinkEditError(&ler, &lerno, &file, &errstr); | 886 } |
871 if ((dls->flags & DL_IN_LIST) == 0) | 887 |
872 { | 888 static void |
873 SDL_free(dls); | 889 dlcompat_init_func (void) |
874 } | 890 { |
875 error(errstr); | 891 _dyld_func_lookup ("__dyld_NSAddImage", (void **) &dyld_NSAddImage); |
876 return NULL; | 892 _dyld_func_lookup ("__dyld_NSIsSymbolNameDefinedInImage", |
877 } | 893 (void **) &dyld_NSIsSymbolNameDefinedInImage); |
878 | 894 _dyld_func_lookup ("__dyld_NSLookupSymbolInImage", |
879 insertStatus(dls, sbuf); | 895 (void **) &dyld_NSLookupSymbolInImage); |
880 dls = reference(dls, mode); | 896 if (pthread_mutex_init (&dlcompat_mutex, NULL)) |
881 if ((init = dlsymIntern(dls, "__init", 0))) | 897 exit (1); |
882 { | 898 if (pthread_key_create (&dlerror_key, &dlerrorfree)) |
883 debug("calling _init()"); | 899 exit (1); |
884 init(); | 900 } |
885 } | 901 |
886 return dls; | 902 static void |
887 } | 903 resetdlerror () |
888 | 904 { |
889 inline static void dlcompat_init_check(void) | 905 struct dlthread *tss; |
890 { | 906 tss = pthread_getspecific (dlerror_key); |
891 static pthread_mutex_t l = PTHREAD_MUTEX_INITIALIZER; | 907 tss->errset = 0; |
892 static int init_done = 0; | 908 } |
893 | 909 |
894 pthread_mutex_lock(&l); | 910 static void |
895 if (!init_done) { | 911 dlerrorfree (void *data) |
896 dlcompat_init_func(); | 912 { |
897 init_done = 1; | 913 SDL_free (data); |
898 } | |
899 pthread_mutex_unlock(&l); | |
900 } | |
901 | |
902 static void dlcompat_init_func(void) | |
903 { | |
904 _dyld_func_lookup("__dyld_NSAddImage", (void **)&dyld_NSAddImage); | |
905 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage", | |
906 (void **)&dyld_NSIsSymbolNameDefinedInImage); | |
907 _dyld_func_lookup("__dyld_NSLookupSymbolInImage", (void **)&dyld_NSLookupSymbolInImage); | |
908 if (pthread_mutex_init(&dlcompat_mutex, NULL)) | |
909 exit(1); | |
910 if (pthread_key_create(&dlerror_key, &dlerrorfree)) | |
911 exit(1); | |
912 } | |
913 | |
914 static void resetdlerror() | |
915 { | |
916 struct dlthread *tss; | |
917 tss = pthread_getspecific(dlerror_key); | |
918 tss->errset = 0; | |
919 } | |
920 | |
921 static void dlerrorfree(void *data) | |
922 { | |
923 SDL_free(data); | |
924 } | 914 } |
925 | 915 |
926 /* We kind of want a recursive lock here, but meet a little trouble | 916 /* We kind of want a recursive lock here, but meet a little trouble |
927 * because they are not available pre OS X 10.2, so we fake it | 917 * because they are not available pre OS X 10.2, so we fake it |
928 * using thread specific storage to keep a lock count | 918 * using thread specific storage to keep a lock count |
929 */ | 919 */ |
930 static inline void dolock(void) | 920 static inline void |
931 { | 921 dolock (void) |
932 int err = 0; | 922 { |
933 struct dlthread *tss; | 923 int err = 0; |
934 dlcompat_init_check(); | 924 struct dlthread *tss; |
935 tss = pthread_getspecific(dlerror_key); | 925 dlcompat_init_check (); |
936 if (!tss) | 926 tss = pthread_getspecific (dlerror_key); |
937 { | 927 if (!tss) { |
938 tss = SDL_malloc(sizeof(struct dlthread)); | 928 tss = SDL_malloc (sizeof (struct dlthread)); |
939 tss->lockcnt = 0; | 929 tss->lockcnt = 0; |
940 tss->errset = 0; | 930 tss->errset = 0; |
941 if (pthread_setspecific(dlerror_key, tss)) | 931 if (pthread_setspecific (dlerror_key, tss)) { |
942 { | 932 fprintf (stderr, "dlcompat: pthread_setspecific failed\n"); |
943 fprintf(stderr,"dlcompat: pthread_setspecific failed\n"); | 933 exit (1); |
944 exit(1); | 934 } |
945 } | 935 } |
946 } | 936 if (!tss->lockcnt) |
947 if (!tss->lockcnt) | 937 err = pthread_mutex_lock (&dlcompat_mutex); |
948 err = pthread_mutex_lock(&dlcompat_mutex); | 938 tss->lockcnt = tss->lockcnt + 1; |
949 tss->lockcnt = tss->lockcnt +1; | 939 if (err) |
950 if (err) | 940 exit (err); |
951 exit(err); | 941 } |
952 } | 942 |
953 | 943 static inline void |
954 static inline void dounlock(void) | 944 dounlock (void) |
955 { | 945 { |
956 int err = 0; | 946 int err = 0; |
957 struct dlthread *tss; | 947 struct dlthread *tss; |
958 tss = pthread_getspecific(dlerror_key); | 948 tss = pthread_getspecific (dlerror_key); |
959 tss->lockcnt = tss->lockcnt -1; | 949 tss->lockcnt = tss->lockcnt - 1; |
960 if (!tss->lockcnt) | 950 if (!tss->lockcnt) |
961 err = pthread_mutex_unlock(&dlcompat_mutex); | 951 err = pthread_mutex_unlock (&dlcompat_mutex); |
962 if (err) | 952 if (err) |
963 exit(err); | 953 exit (err); |
964 } | 954 } |
965 | 955 |
966 static void *SDL_OSX_dlopen(const char *path, int mode) | 956 static void * |
967 { | 957 SDL_OSX_dlopen (const char *path, int mode) |
968 const struct stat *sbuf; | 958 { |
969 struct dlstatus *dls; | 959 const struct stat *sbuf; |
970 const char *fullPath; | 960 struct dlstatus *dls; |
971 | 961 const char *fullPath; |
972 dolock(); | 962 |
973 resetdlerror(); | 963 dolock (); |
974 if (!path) | 964 resetdlerror (); |
975 { | 965 if (!path) { |
976 dls = &mainStatus; | 966 dls = &mainStatus; |
977 goto dlopenok; | 967 goto dlopenok; |
978 } | 968 } |
979 if (!(sbuf = findFile(path, &fullPath))) | 969 if (!(sbuf = findFile (path, &fullPath))) { |
980 { | 970 error ("file \"%s\" not found", path); |
981 error("file \"%s\" not found", path); | 971 goto dlopenerror; |
982 goto dlopenerror; | 972 } |
983 } | 973 /* Now checks that it hasn't been closed already */ |
984 /* Now checks that it hasn't been closed already */ | 974 if ((dls = lookupStatus (sbuf)) && (dls->refs > 0)) { |
985 if ((dls = lookupStatus(sbuf)) && (dls->refs > 0)) | 975 /* debug("status found"); */ |
986 { | 976 dls = reference (dls, mode); |
987 /* debug("status found"); */ | 977 goto dlopenok; |
988 dls = reference(dls, mode); | 978 } |
989 goto dlopenok; | |
990 } | |
991 #ifdef RTLD_NOLOAD | 979 #ifdef RTLD_NOLOAD |
992 if (isFlagSet(mode, RTLD_NOLOAD)) | 980 if (isFlagSet (mode, RTLD_NOLOAD)) { |
993 { | 981 error ("no existing handle and RTLD_NOLOAD specified"); |
994 error("no existing handle and RTLD_NOLOAD specified"); | 982 goto dlopenerror; |
995 goto dlopenerror; | 983 } |
996 } | 984 #endif |
997 #endif | 985 if (isFlagSet (mode, RTLD_LAZY) && isFlagSet (mode, RTLD_NOW)) { |
998 if (isFlagSet(mode, RTLD_LAZY) && isFlagSet(mode, RTLD_NOW)) | 986 error ("how can I load something both RTLD_LAZY and RTLD_NOW?"); |
999 { | 987 goto dlopenerror; |
1000 error("how can I load something both RTLD_LAZY and RTLD_NOW?"); | 988 } |
1001 goto dlopenerror; | 989 dls = loadModule (fullPath, sbuf, mode); |
1002 } | 990 |
1003 dls = loadModule(fullPath, sbuf, mode); | |
1004 | |
1005 dlopenok: | 991 dlopenok: |
1006 dounlock(); | 992 dounlock (); |
1007 return (void *)dls; | 993 return (void *) dls; |
1008 dlopenerror: | 994 dlopenerror: |
1009 dounlock(); | 995 dounlock (); |
1010 return NULL; | 996 return NULL; |
1011 } | 997 } |
1012 | 998 |
1013 #if !FINK_BUILD | 999 #if !FINK_BUILD |
1014 static void *SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol) | 1000 static void * |
1015 { | 1001 SDL_OSX_dlsym (void *dl_restrict handle, const char *dl_restrict symbol) |
1016 int sym_len = SDL_strlen(symbol); | 1002 { |
1017 void *value = NULL; | 1003 int sym_len = SDL_strlen (symbol); |
1018 char *malloc_sym = NULL; | 1004 void *value = NULL; |
1019 dolock(); | 1005 char *malloc_sym = NULL; |
1020 malloc_sym = SDL_malloc(sym_len + 2); | 1006 dolock (); |
1021 if (malloc_sym) | 1007 malloc_sym = SDL_malloc (sym_len + 2); |
1022 { | 1008 if (malloc_sym) { |
1023 SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol); | 1009 SDL_snprintf (malloc_sym, sym_len + 2, "_%s", symbol); |
1024 value = dlsymIntern(handle, malloc_sym, 1); | 1010 value = dlsymIntern (handle, malloc_sym, 1); |
1025 SDL_free(malloc_sym); | 1011 SDL_free (malloc_sym); |
1026 } | 1012 } else { |
1027 else | 1013 error ("Unable to allocate memory"); |
1028 { | 1014 goto dlsymerror; |
1029 error("Unable to allocate memory"); | 1015 } |
1030 goto dlsymerror; | 1016 dounlock (); |
1031 } | 1017 return value; |
1032 dounlock(); | |
1033 return value; | |
1034 dlsymerror: | 1018 dlsymerror: |
1035 dounlock(); | 1019 dounlock (); |
1036 return NULL; | 1020 return NULL; |
1037 } | 1021 } |
1038 #endif | 1022 #endif |
1039 | 1023 |
1040 #if FINK_BUILD | 1024 #if FINK_BUILD |
1041 | 1025 |
1042 static void *dlsym_prepend_underscore(void *handle, const char *symbol) | 1026 static void * |
1043 { | 1027 dlsym_prepend_underscore (void *handle, const char *symbol) |
1044 void *answer; | 1028 { |
1045 dolock(); | 1029 void *answer; |
1046 answer = dlsym_prepend_underscore_intern(handle, symbol); | 1030 dolock (); |
1047 dounlock(); | 1031 answer = dlsym_prepend_underscore_intern (handle, symbol); |
1048 return answer; | 1032 dounlock (); |
1049 } | 1033 return answer; |
1050 | 1034 } |
1051 static void *dlsym_prepend_underscore_intern(void *handle, const char *symbol) | 1035 |
1036 static void * | |
1037 dlsym_prepend_underscore_intern (void *handle, const char *symbol) | |
1052 { | 1038 { |
1053 /* | 1039 /* |
1054 * A quick and easy way for porting packages which call dlsym(handle,"sym") | 1040 * A quick and easy way for porting packages which call dlsym(handle,"sym") |
1055 * If the porter adds -Ddlsym=dlsym_prepend_underscore to the CFLAGS then | 1041 * If the porter adds -Ddlsym=dlsym_prepend_underscore to the CFLAGS then |
1056 * this function will be called, and will add the required underscore. | 1042 * this function will be called, and will add the required underscore. |
1057 * | 1043 * |
1058 * Note that I haven't figured out yet which should be "standard", prepend | 1044 * Note that I haven't figured out yet which should be "standard", prepend |
1059 * the underscore always, or not at all. These global functions need to go away | 1045 * the underscore always, or not at all. These global functions need to go away |
1060 * for opendarwin. | 1046 * for opendarwin. |
1061 */ | 1047 */ |
1062 int sym_len = SDL_strlen(symbol); | 1048 int sym_len = SDL_strlen (symbol); |
1063 void *value = NULL; | 1049 void *value = NULL; |
1064 char *malloc_sym = NULL; | 1050 char *malloc_sym = NULL; |
1065 malloc_sym = SDL_malloc(sym_len + 2); | 1051 malloc_sym = SDL_malloc (sym_len + 2); |
1066 if (malloc_sym) | 1052 if (malloc_sym) { |
1067 { | 1053 SDL_snprintf (malloc_sym, sym_len + 2, "_%s", symbol); |
1068 SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol); | 1054 value = dlsymIntern (handle, malloc_sym, 1); |
1069 value = dlsymIntern(handle, malloc_sym, 1); | 1055 SDL_free (malloc_sym); |
1070 SDL_free(malloc_sym); | 1056 } else { |
1071 } | 1057 error ("Unable to allocate memory"); |
1072 else | 1058 } |
1073 { | 1059 return value; |
1074 error("Unable to allocate memory"); | 1060 } |
1075 } | 1061 |
1076 return value; | 1062 static void * |
1077 } | 1063 dlsym_auto_underscore (void *handle, const char *symbol) |
1078 | 1064 { |
1079 static void *dlsym_auto_underscore(void *handle, const char *symbol) | 1065 void *answer; |
1080 { | 1066 dolock (); |
1081 void *answer; | 1067 answer = dlsym_auto_underscore_intern (handle, symbol); |
1082 dolock(); | 1068 dounlock (); |
1083 answer = dlsym_auto_underscore_intern(handle, symbol); | 1069 return answer; |
1084 dounlock(); | 1070 |
1085 return answer; | 1071 } |
1086 | 1072 static void * |
1087 } | 1073 dlsym_auto_underscore_intern (void *handle, const char *symbol) |
1088 static void *dlsym_auto_underscore_intern(void *handle, const char *symbol) | 1074 { |
1089 { | 1075 struct dlstatus *dls = handle; |
1090 struct dlstatus *dls = handle; | 1076 void *addr = 0; |
1091 void *addr = 0; | 1077 addr = dlsymIntern (dls, symbol, 0); |
1092 addr = dlsymIntern(dls, symbol, 0); | 1078 if (!addr) |
1093 if (!addr) | 1079 addr = dlsym_prepend_underscore_intern (handle, symbol); |
1094 addr = dlsym_prepend_underscore_intern(handle, symbol); | 1080 return addr; |
1095 return addr; | 1081 } |
1096 } | 1082 |
1097 | 1083 |
1098 | 1084 static void * |
1099 static void *SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol) | 1085 SDL_OSX_dlsym (void *dl_restrict handle, const char *dl_restrict symbol) |
1100 { | 1086 { |
1101 struct dlstatus *dls = handle; | 1087 struct dlstatus *dls = handle; |
1102 void *addr = 0; | 1088 void *addr = 0; |
1103 dolock(); | 1089 dolock (); |
1104 addr = dlsymIntern(dls, symbol, 1); | 1090 addr = dlsymIntern (dls, symbol, 1); |
1105 dounlock(); | 1091 dounlock (); |
1106 return addr; | 1092 return addr; |
1107 } | 1093 } |
1108 #endif | 1094 #endif |
1109 | 1095 |
1110 static int SDL_OSX_dlclose(void *handle) | 1096 static int |
1111 { | 1097 SDL_OSX_dlclose (void *handle) |
1112 struct dlstatus *dls = handle; | 1098 { |
1113 dolock(); | 1099 struct dlstatus *dls = handle; |
1114 resetdlerror(); | 1100 dolock (); |
1115 if (!isValidStatus(dls)) | 1101 resetdlerror (); |
1116 { | 1102 if (!isValidStatus (dls)) { |
1117 goto dlcloseerror; | 1103 goto dlcloseerror; |
1118 } | 1104 } |
1119 if (dls->module == MAGIC_DYLIB_MOD) | 1105 if (dls->module == MAGIC_DYLIB_MOD) { |
1120 { | 1106 const char *name; |
1121 const char *name; | 1107 if (!dls->lib) { |
1122 if (!dls->lib) | 1108 name = "global context"; |
1123 { | 1109 } else { |
1124 name = "global context"; | 1110 name = get_lib_name (dls->lib); |
1125 } | 1111 } |
1126 else | 1112 warning ("trying to close a .dylib!"); |
1127 { | 1113 error ("Not closing \"%s\" - dynamic libraries cannot be closed", |
1128 name = get_lib_name(dls->lib); | 1114 name); |
1129 } | 1115 goto dlcloseerror; |
1130 warning("trying to close a .dylib!"); | 1116 } |
1131 error("Not closing \"%s\" - dynamic libraries cannot be closed", name); | 1117 if (!dls->module) { |
1132 goto dlcloseerror; | 1118 error ("module already closed"); |
1133 } | 1119 goto dlcloseerror; |
1134 if (!dls->module) | 1120 } |
1135 { | 1121 |
1136 error("module already closed"); | 1122 if (dls->refs == 1) { |
1137 goto dlcloseerror; | 1123 unsigned long options = 0; |
1138 } | 1124 void (*fini) (void); |
1139 | 1125 if ((fini = dlsymIntern (dls, "__fini", 0))) { |
1140 if (dls->refs == 1) | 1126 debug ("calling _fini()"); |
1141 { | 1127 fini (); |
1142 unsigned long options = 0; | 1128 } |
1143 void (*fini) (void); | 1129 options |= NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES; |
1144 if ((fini = dlsymIntern(dls, "__fini", 0))) | |
1145 { | |
1146 debug("calling _fini()"); | |
1147 fini(); | |
1148 } | |
1149 options |= NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES; | |
1150 #ifdef RTLD_NODELETE | 1130 #ifdef RTLD_NODELETE |
1151 if (isFlagSet(dls->mode, RTLD_NODELETE)) | 1131 if (isFlagSet (dls->mode, RTLD_NODELETE)) |
1152 options |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED; | 1132 options |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED; |
1153 #endif | 1133 #endif |
1154 if (!NSUnLinkModule(dls->module, options)) | 1134 if (!NSUnLinkModule (dls->module, options)) { |
1155 { | 1135 error ("unable to unlink module"); |
1156 error("unable to unlink module"); | 1136 goto dlcloseerror; |
1157 goto dlcloseerror; | 1137 } |
1158 } | 1138 dls->refs--; |
1159 dls->refs--; | 1139 dls->module = 0; |
1160 dls->module = 0; | 1140 /* Note: the dlstatus struct dls is neither removed from the list |
1161 /* Note: the dlstatus struct dls is neither removed from the list | 1141 * nor is the memory it occupies freed. This shouldn't pose a |
1162 * nor is the memory it occupies freed. This shouldn't pose a | 1142 * problem in mostly all cases, though. |
1163 * problem in mostly all cases, though. | 1143 */ |
1164 */ | 1144 } |
1165 } | 1145 dounlock (); |
1166 dounlock(); | 1146 return 0; |
1167 return 0; | |
1168 dlcloseerror: | 1147 dlcloseerror: |
1169 dounlock(); | 1148 dounlock (); |
1170 return 1; | 1149 return 1; |
1171 } | 1150 } |
1172 | 1151 |
1173 static const char *SDL_OSX_dlerror(void) | 1152 static const char * |
1174 { | 1153 SDL_OSX_dlerror (void) |
1175 struct dlthread *tss; | 1154 { |
1176 const char * err_str = NULL; | 1155 struct dlthread *tss; |
1177 dlcompat_init_check(); | 1156 const char *err_str = NULL; |
1178 tss = pthread_getspecific(dlerror_key); | 1157 dlcompat_init_check (); |
1179 if (tss != NULL && tss->errset != 0) { | 1158 tss = pthread_getspecific (dlerror_key); |
1180 tss->errset = 0; | 1159 if (tss != NULL && tss->errset != 0) { |
1181 err_str = tss->errstr; | 1160 tss->errset = 0; |
1182 } | 1161 err_str = tss->errstr; |
1183 return (err_str); | 1162 } |
1163 return (err_str); | |
1184 } | 1164 } |
1185 | 1165 |
1186 /* Given an address, return the mach_header for the image containing it | 1166 /* Given an address, return the mach_header for the image containing it |
1187 * or zero if the given address is not contained in any loaded images. | 1167 * or zero if the given address is not contained in any loaded images. |
1188 */ | 1168 */ |
1189 static const struct mach_header *image_for_address(const void *address) | 1169 static const struct mach_header * |
1190 { | 1170 image_for_address (const void *address) |
1191 unsigned long i; | 1171 { |
1192 unsigned long j; | 1172 unsigned long i; |
1193 unsigned long count = _dyld_image_count(); | 1173 unsigned long j; |
1194 const struct mach_header *mh = 0; | 1174 unsigned long count = _dyld_image_count (); |
1195 struct load_command *lc = 0; | 1175 const struct mach_header *mh = 0; |
1196 unsigned long addr = 0; | 1176 struct load_command *lc = 0; |
1197 for (i = 0; i < count; i++) | 1177 unsigned long addr = 0; |
1198 { | 1178 for (i = 0; i < count; i++) { |
1199 addr = (unsigned long)address - _dyld_get_image_vmaddr_slide(i); | 1179 addr = (unsigned long) address - _dyld_get_image_vmaddr_slide (i); |
1200 mh = _dyld_get_image_header(i); | 1180 mh = _dyld_get_image_header (i); |
1201 if (mh) | 1181 if (mh) { |
1202 { | 1182 lc = (struct load_command *) ((char *) mh + |
1203 lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); | 1183 sizeof (struct mach_header)); |
1204 for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) | 1184 for (j = 0; j < mh->ncmds; |
1205 { | 1185 j++, lc = |
1206 if (LC_SEGMENT == lc->cmd && | 1186 (struct load_command *) ((char *) lc + lc->cmdsize)) { |
1207 addr >= ((struct segment_command *)lc)->vmaddr && | 1187 if (LC_SEGMENT == lc->cmd && |
1208 addr < | 1188 addr >= ((struct segment_command *) lc)->vmaddr && |
1209 ((struct segment_command *)lc)->vmaddr + ((struct segment_command *)lc)->vmsize) | 1189 addr < |
1210 { | 1190 ((struct segment_command *) lc)->vmaddr + |
1211 goto image_found; | 1191 ((struct segment_command *) lc)->vmsize) { |
1212 } | 1192 goto image_found; |
1213 } | 1193 } |
1214 } | 1194 } |
1215 mh = 0; | 1195 } |
1216 } | 1196 mh = 0; |
1197 } | |
1217 image_found: | 1198 image_found: |
1218 return mh; | 1199 return mh; |
1219 } | 1200 } |
1220 | 1201 |
1221 #if 0 /* unused */ | 1202 #if 0 /* unused */ |
1222 static int SDL_OSX_dladdr(const void * dl_restrict p, SDL_OSX_Dl_info * dl_restrict info) | 1203 static int |
1204 SDL_OSX_dladdr (const void *dl_restrict p, SDL_OSX_Dl_info * dl_restrict info) | |
1223 { | 1205 { |
1224 /* | 1206 /* |
1225 FIXME: USe the routine image_for_address. | 1207 FIXME: USe the routine image_for_address. |
1226 */ | 1208 */ |
1227 unsigned long i; | 1209 unsigned long i; |
1228 unsigned long j; | 1210 unsigned long j; |
1229 unsigned long count = _dyld_image_count(); | 1211 unsigned long count = _dyld_image_count (); |
1230 struct mach_header *mh = 0; | 1212 struct mach_header *mh = 0; |
1231 struct load_command *lc = 0; | 1213 struct load_command *lc = 0; |
1232 unsigned long addr = NULL; | 1214 unsigned long addr = NULL; |
1233 unsigned long table_off = (unsigned long)0; | 1215 unsigned long table_off = (unsigned long) 0; |
1234 int found = 0; | 1216 int found = 0; |
1235 if (!info) | 1217 if (!info) |
1236 return 0; | 1218 return 0; |
1237 dolock(); | 1219 dolock (); |
1238 resetdlerror(); | 1220 resetdlerror (); |
1239 info->dli_fname = 0; | 1221 info->dli_fname = 0; |
1240 info->dli_fbase = 0; | 1222 info->dli_fbase = 0; |
1241 info->dli_sname = 0; | 1223 info->dli_sname = 0; |
1242 info->dli_saddr = 0; | 1224 info->dli_saddr = 0; |
1243 /* Some of this was swiped from code posted by Douglas Davidson <ddavidso AT apple DOT com> | 1225 /* Some of this was swiped from code posted by Douglas Davidson <ddavidso AT apple DOT com> |
1244 * to darwin-development AT lists DOT apple DOT com and slightly modified | 1226 * to darwin-development AT lists DOT apple DOT com and slightly modified |
1245 */ | 1227 */ |
1246 for (i = 0; i < count; i++) | 1228 for (i = 0; i < count; i++) { |
1247 { | 1229 addr = (unsigned long) p - _dyld_get_image_vmaddr_slide (i); |
1248 addr = (unsigned long)p - _dyld_get_image_vmaddr_slide(i); | 1230 mh = _dyld_get_image_header (i); |
1249 mh = _dyld_get_image_header(i); | 1231 if (mh) { |
1250 if (mh) | 1232 lc = (struct load_command *) ((char *) mh + |
1251 { | 1233 sizeof (struct mach_header)); |
1252 lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); | 1234 for (j = 0; j < mh->ncmds; |
1253 for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) | 1235 j++, lc = |
1254 { | 1236 (struct load_command *) ((char *) lc + lc->cmdsize)) { |
1255 if (LC_SEGMENT == lc->cmd && | 1237 if (LC_SEGMENT == lc->cmd && |
1256 addr >= ((struct segment_command *)lc)->vmaddr && | 1238 addr >= ((struct segment_command *) lc)->vmaddr && |
1257 addr < | 1239 addr < |
1258 ((struct segment_command *)lc)->vmaddr + ((struct segment_command *)lc)->vmsize) | 1240 ((struct segment_command *) lc)->vmaddr + |
1259 { | 1241 ((struct segment_command *) lc)->vmsize) { |
1260 info->dli_fname = _dyld_get_image_name(i); | 1242 info->dli_fname = _dyld_get_image_name (i); |
1261 info->dli_fbase = (void *)mh; | 1243 info->dli_fbase = (void *) mh; |
1262 found = 1; | 1244 found = 1; |
1263 break; | 1245 break; |
1264 } | 1246 } |
1265 } | 1247 } |
1266 if (found) | 1248 if (found) |
1267 break; | 1249 break; |
1268 } | 1250 } |
1269 } | 1251 } |
1270 if (!found) | 1252 if (!found) { |
1271 { | 1253 dounlock (); |
1272 dounlock(); | 1254 return 0; |
1273 return 0; | 1255 } |
1274 } | 1256 lc = (struct load_command *) ((char *) mh + sizeof (struct mach_header)); |
1275 lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); | 1257 for (j = 0; j < mh->ncmds; |
1276 for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) | 1258 j++, lc = (struct load_command *) ((char *) lc + lc->cmdsize)) { |
1277 { | 1259 if (LC_SEGMENT == lc->cmd) { |
1278 if (LC_SEGMENT == lc->cmd) | 1260 if (!SDL_strcmp |
1279 { | 1261 (((struct segment_command *) lc)->segname, "__LINKEDIT")) |
1280 if (!SDL_strcmp(((struct segment_command *)lc)->segname, "__LINKEDIT")) | 1262 break; |
1281 break; | 1263 } |
1282 } | 1264 } |
1283 } | 1265 table_off = |
1284 table_off = | 1266 ((unsigned long) ((struct segment_command *) lc)->vmaddr) - |
1285 ((unsigned long)((struct segment_command *)lc)->vmaddr) - | 1267 ((unsigned long) ((struct segment_command *) lc)->fileoff) + |
1286 ((unsigned long)((struct segment_command *)lc)->fileoff) + _dyld_get_image_vmaddr_slide(i); | 1268 _dyld_get_image_vmaddr_slide (i); |
1287 debug("table off %x", table_off); | 1269 debug ("table off %x", table_off); |
1288 | 1270 |
1289 lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); | 1271 lc = (struct load_command *) ((char *) mh + sizeof (struct mach_header)); |
1290 for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) | 1272 for (j = 0; j < mh->ncmds; |
1291 { | 1273 j++, lc = (struct load_command *) ((char *) lc + lc->cmdsize)) { |
1292 if (LC_SYMTAB == lc->cmd) | 1274 if (LC_SYMTAB == lc->cmd) { |
1293 { | 1275 |
1294 | 1276 struct nlist *symtable = |
1295 struct nlist *symtable = (struct nlist *)(((struct symtab_command *)lc)->symoff + table_off); | 1277 (struct nlist *) (((struct symtab_command *) lc)->symoff + |
1296 unsigned long numsyms = ((struct symtab_command *)lc)->nsyms; | 1278 table_off); |
1297 struct nlist *nearest = NULL; | 1279 unsigned long numsyms = ((struct symtab_command *) lc)->nsyms; |
1298 unsigned long diff = 0xffffffff; | 1280 struct nlist *nearest = NULL; |
1299 unsigned long strtable = (unsigned long)(((struct symtab_command *)lc)->stroff + table_off); | 1281 unsigned long diff = 0xffffffff; |
1300 debug("symtable %x", symtable); | 1282 unsigned long strtable = |
1301 for (i = 0; i < numsyms; i++) | 1283 (unsigned long) (((struct symtab_command *) lc)->stroff + |
1302 { | 1284 table_off); |
1303 /* Ignore the following kinds of Symbols */ | 1285 debug ("symtable %x", symtable); |
1304 if ((!symtable->n_value) /* Undefined */ | 1286 for (i = 0; i < numsyms; i++) { |
1305 || (symtable->n_type >= N_PEXT) /* Debug symbol */ | 1287 /* Ignore the following kinds of Symbols */ |
1306 || (!(symtable->n_type & N_EXT)) /* Local Symbol */ | 1288 if ((!symtable->n_value) /* Undefined */ |
1307 ) | 1289 ||(symtable->n_type >= N_PEXT) /* Debug symbol */ |
1308 { | 1290 ||(!(symtable->n_type & N_EXT)) /* Local Symbol */ |
1309 symtable++; | 1291 ) { |
1310 continue; | 1292 symtable++; |
1311 } | 1293 continue; |
1312 if ((addr >= symtable->n_value) && (diff >= (symtable->n_value - addr))) | 1294 } |
1313 { | 1295 if ((addr >= symtable->n_value) |
1314 diff = (unsigned long)symtable->n_value - addr; | 1296 && (diff >= (symtable->n_value - addr))) { |
1315 nearest = symtable; | 1297 diff = (unsigned long) symtable->n_value - addr; |
1316 } | 1298 nearest = symtable; |
1317 symtable++; | 1299 } |
1318 } | 1300 symtable++; |
1319 if (nearest) | 1301 } |
1320 { | 1302 if (nearest) { |
1321 info->dli_saddr = nearest->n_value + ((void *)p - addr); | 1303 info->dli_saddr = nearest->n_value + ((void *) p - addr); |
1322 info->dli_sname = (char *)(strtable + nearest->n_un.n_strx); | 1304 info->dli_sname = (char *) (strtable + nearest->n_un.n_strx); |
1323 } | 1305 } |
1324 } | 1306 } |
1325 } | 1307 } |
1326 dounlock(); | 1308 dounlock (); |
1327 return 1; | 1309 return 1; |
1328 } | 1310 } |
1329 #endif | 1311 #endif |
1330 | 1312 |
1331 /* | 1313 /* |
1332 * Implement the dlfunc() interface, which behaves exactly the same as | 1314 * Implement the dlfunc() interface, which behaves exactly the same as |
1335 * about undefined behavior, and is intended as prior art for future | 1317 * about undefined behavior, and is intended as prior art for future |
1336 * POSIX standardization. This function requires that all pointer types | 1318 * POSIX standardization. This function requires that all pointer types |
1337 * have the same representation, which is true on all platforms FreeBSD | 1319 * have the same representation, which is true on all platforms FreeBSD |
1338 * runs on, but is not guaranteed by the C standard. | 1320 * runs on, but is not guaranteed by the C standard. |
1339 */ | 1321 */ |
1340 #if 0 | 1322 #if 0 |
1341 static dlfunc_t SDL_OSX_dlfunc(void * dl_restrict handle, const char * dl_restrict symbol) | 1323 static dlfunc_t |
1342 { | 1324 SDL_OSX_dlfunc (void *dl_restrict handle, const char *dl_restrict symbol) |
1343 union | 1325 { |
1344 { | 1326 union |
1345 void *d; | 1327 { |
1346 dlfunc_t f; | 1328 void *d; |
1347 } rv; | 1329 dlfunc_t f; |
1348 int sym_len = SDL_strlen(symbol); | 1330 } rv; |
1349 char *malloc_sym = NULL; | 1331 int sym_len = SDL_strlen (symbol); |
1350 dolock(); | 1332 char *malloc_sym = NULL; |
1351 malloc_sym = SDL_malloc(sym_len + 2); | 1333 dolock (); |
1352 if (malloc_sym) | 1334 malloc_sym = SDL_malloc (sym_len + 2); |
1353 { | 1335 if (malloc_sym) { |
1354 SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol); | 1336 SDL_snprintf (malloc_sym, sym_len + 2, "_%s", symbol); |
1355 rv.d = dlsymIntern(handle, malloc_sym, 1); | 1337 rv.d = dlsymIntern (handle, malloc_sym, 1); |
1356 SDL_free(malloc_sym); | 1338 SDL_free (malloc_sym); |
1357 } | 1339 } else { |
1358 else | 1340 error ("Unable to allocate memory"); |
1359 { | 1341 goto dlfuncerror; |
1360 error("Unable to allocate memory"); | 1342 } |
1361 goto dlfuncerror; | 1343 dounlock (); |
1362 } | 1344 return rv.f; |
1363 dounlock(); | |
1364 return rv.f; | |
1365 dlfuncerror: | 1345 dlfuncerror: |
1366 dounlock(); | 1346 dounlock (); |
1367 return NULL; | 1347 return NULL; |
1368 } | 1348 } |
1369 #endif | 1349 #endif |
1370 | 1350 |
1371 | 1351 |
1372 | 1352 |
1376 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | 1356 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
1377 /* System dependent library loading routines */ | 1357 /* System dependent library loading routines */ |
1378 | 1358 |
1379 #include "SDL_loadso.h" | 1359 #include "SDL_loadso.h" |
1380 | 1360 |
1381 void *SDL_LoadObject(const char *sofile) | 1361 void * |
1382 { | 1362 SDL_LoadObject (const char *sofile) |
1383 void *handle = SDL_OSX_dlopen(sofile, RTLD_NOW); | 1363 { |
1384 const char *loaderror = SDL_OSX_dlerror(); | 1364 void *handle = SDL_OSX_dlopen (sofile, RTLD_NOW); |
1385 if ( handle == NULL ) { | 1365 const char *loaderror = SDL_OSX_dlerror (); |
1386 SDL_SetError("Failed loading %s: %s", sofile, loaderror); | 1366 if (handle == NULL) { |
1387 } | 1367 SDL_SetError ("Failed loading %s: %s", sofile, loaderror); |
1388 return(handle); | 1368 } |
1389 } | 1369 return (handle); |
1390 | 1370 } |
1391 void *SDL_LoadFunction(void *handle, const char *name) | 1371 |
1392 { | 1372 void * |
1393 void *symbol = SDL_OSX_dlsym(handle, name); | 1373 SDL_LoadFunction (void *handle, const char *name) |
1394 if ( symbol == NULL ) { | 1374 { |
1395 SDL_SetError("Failed loading %s: %s", name, SDL_OSX_dlerror()); | 1375 void *symbol = SDL_OSX_dlsym (handle, name); |
1396 } | 1376 if (symbol == NULL) { |
1397 return(symbol); | 1377 SDL_SetError ("Failed loading %s: %s", name, SDL_OSX_dlerror ()); |
1398 } | 1378 } |
1399 | 1379 return (symbol); |
1400 void SDL_UnloadObject(void *handle) | 1380 } |
1401 { | 1381 |
1402 if ( handle != NULL ) { | 1382 void |
1403 SDL_OSX_dlclose(handle); | 1383 SDL_UnloadObject (void *handle) |
1404 } | 1384 { |
1385 if (handle != NULL) { | |
1386 SDL_OSX_dlclose (handle); | |
1387 } | |
1405 } | 1388 } |
1406 | 1389 |
1407 #endif /* SDL_LOADSO_DLCOMPAT */ | 1390 #endif /* SDL_LOADSO_DLCOMPAT */ |
1391 /* vi: set ts=4 sw=4 expandtab: */ |