comparison src/loadso/macosx/SDL_dlcompat.c @ 1895:c121d94672cb

SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
author Sam Lantinga <slouken@libsdl.org>
date Mon, 10 Jul 2006 21:04:37 +0000
parents e308d020d315
children e1da92da346c
comparison
equal deleted inserted replaced
1894:c69cee13dd76 1895:c121d94672cb
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]; */
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,
249 int canSetError);
241 static struct dlstatus *allocStatus(void); 250 static struct dlstatus *allocStatus(void);
242 static struct dlstatus *loadModule(const char *path, const struct stat *sbuf, int mode); 251 static struct dlstatus *loadModule(const char *path, const struct stat *sbuf,
243 static NSSymbol search_linked_libs(const struct mach_header *mh, const char *symbol); 252 int mode);
253 static NSSymbol search_linked_libs(const struct mach_header *mh,
254 const char *symbol);
244 static const char *get_lib_name(const struct mach_header *mh); 255 static const char *get_lib_name(const struct mach_header *mh);
245 static const struct mach_header *get_mach_header_from_NSModule(NSModule mod); 256 static const struct mach_header *get_mach_header_from_NSModule(NSModule mod);
246 static void dlcompat_init_func(void); 257 static void dlcompat_init_func(void);
247 static inline void dlcompat_init_check(void); 258 static inline void dlcompat_init_check(void);
248 static inline void dolock(void); 259 static inline void dolock(void);
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,
274 const char *symbol);
263 static void *dlsym_auto_underscore_intern(void *handle, 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) + 4;
376 SDL_snprintf(buf, buf_size, "%s%s%s%s%s%c", dyldlp, (dyldlp[0] ? ":" : ""), ldlp, (ldlp[0] ? ":" : ""), 389 buf = SDL_malloc(buf_size);
377 stdpath, '\0'); 390 SDL_snprintf(buf, buf_size, "%s%s%s%s%s%c", dyldlp,
378 } 391 (dyldlp[0] ? ":" : ""), ldlp, (ldlp[0] ? ":" : ""),
379 return buf; 392 stdpath, '\0');
393 }
394 return buf;
380 } 395 }
381 396
382 /* Returns the ith search path from the list as computed by searchList() */ 397 /* Returns the ith search path from the list as computed by searchList() */
383 static const char *getSearchPath(int i) 398 static const char *
384 { 399 getSearchPath(int i)
385 static const char *list = 0; 400 {
386 static char **path = (char **)0; 401 static const char *list = 0;
387 static int end = 0; 402 static char **path = (char **) 0;
388 static int numsize = MAX_SEARCH_PATHS; 403 static int end = 0;
389 static char **tmp; 404 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 */ 405 static char **tmp;
391 if (i == -1) 406 /* So we can call SDL_free() in the "destructor" we use i=-1 to return the alloc'd array */
392 { 407 if (i == -1) {
393 return (const char*)path; 408 return (const char *) path;
394 } 409 }
395 if (!path) 410 if (!path) {
396 { 411 path = (char **) SDL_calloc(MAX_SEARCH_PATHS, sizeof(char **));
397 path = (char **)SDL_calloc(MAX_SEARCH_PATHS, sizeof(char **)); 412 }
398 } 413 if (!list && !end)
399 if (!list && !end) 414 list = searchList();
400 list = searchList(); 415 if (i >= (numsize)) {
401 if (i >= (numsize)) 416 debug("Increasing size for long PATH");
402 { 417 tmp =
403 debug("Increasing size for long PATH"); 418 (char **) SDL_calloc((MAX_SEARCH_PATHS + numsize),
404 tmp = (char **)SDL_calloc((MAX_SEARCH_PATHS + numsize), sizeof(char **)); 419 sizeof(char **));
405 if (tmp) 420 if (tmp) {
406 { 421 SDL_memcpy(tmp, path, sizeof(char **) * numsize);
407 SDL_memcpy(tmp, path, sizeof(char **) * numsize); 422 SDL_free(path);
408 SDL_free(path); 423 path = tmp;
409 path = tmp; 424 numsize += MAX_SEARCH_PATHS;
410 numsize += MAX_SEARCH_PATHS; 425 } else {
411 } 426 return 0;
412 else 427 }
413 { 428 }
414 return 0; 429
415 } 430 while (!path[i] && !end) {
416 } 431 path[i] = strsep((char **) &list, ":");
417 432
418 while (!path[i] && !end) 433 if (path[i][0] == 0)
419 { 434 path[i] = 0;
420 path[i] = strsep((char **)&list, ":"); 435 end = (list == 0);
421 436 }
422 if (path[i][0] == 0) 437 return path[i];
423 path[i] = 0; 438 }
424 end = (list == 0); 439
425 } 440 static const char *
426 return path[i]; 441 getFullPath(int i, const char *file)
427 } 442 {
428 443 static char buf[PATH_MAX];
429 static const char *getFullPath(int i, const char *file) 444 const char *path = getSearchPath(i);
430 { 445 if (path) {
431 static char buf[PATH_MAX]; 446 SDL_snprintf(buf, PATH_MAX, "%s/%s", path, file);
432 const char *path = getSearchPath(i); 447 }
433 if (path) 448 return path ? buf : 0;
434 {
435 SDL_snprintf(buf, PATH_MAX, "%s/%s", path, file);
436 }
437 return path ? buf : 0;
438 } 449 }
439 450
440 /* Given a file name, try to determine the full path for that file. Starts 451 /* 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 452 * its search in the current directory, and then tries all paths in the
442 * search list in the order they are specified there. 453 * search list in the order they are specified there.
443 */ 454 */
444 static const struct stat *findFile(const char *file, const char **fullPath) 455 static const struct stat *
445 { 456 findFile(const char *file, const char **fullPath)
446 int i = 0; 457 {
447 static struct stat sbuf; 458 int i = 0;
448 char *fileName; 459 static struct stat sbuf;
449 debug("finding file %s", file); 460 char *fileName;
450 *fullPath = file; 461 debug("finding file %s", file);
451 if (0 == stat(file, &sbuf)) 462 *fullPath = file;
452 return &sbuf; 463 if (0 == stat(file, &sbuf))
453 if (SDL_strchr(file, '/')) 464 return &sbuf;
454 return 0; /* If the path had a / we don't look in env var places */ 465 if (SDL_strchr(file, '/'))
455 fileName = NULL; 466 return 0; /* If the path had a / we don't look in env var places */
456 if (!fileName) 467 fileName = NULL;
457 fileName = (char *)file; 468 if (!fileName)
458 while ((*fullPath = getFullPath(i++, fileName))) 469 fileName = (char *) file;
459 { 470 while ((*fullPath = getFullPath(i++, fileName))) {
460 if (0 == stat(*fullPath, &sbuf)) 471 if (0 == stat(*fullPath, &sbuf))
461 return &sbuf; 472 return &sbuf;
462 } 473 }
463 ; 474 ;
464 return 0; 475 return 0;
465 } 476 }
466 477
467 /* Determine whether a given dlstatus is valid or not */ 478 /* Determine whether a given dlstatus is valid or not */
468 static int isValidStatus(struct dlstatus *status) 479 static int
469 { 480 isValidStatus(struct dlstatus *status)
470 /* Walk the list to verify status is contained in it */ 481 {
471 struct dlstatus *dls = stqueue; 482 /* Walk the list to verify status is contained in it */
472 while (dls && status != dls) 483 struct dlstatus *dls = stqueue;
473 dls = dls->next; 484 while (dls && status != dls)
474 if (dls == 0) 485 dls = dls->next;
475 error("invalid handle"); 486 if (dls == 0)
476 else if ((dls->module == 0) || (dls->refs == 0)) 487 error("invalid handle");
477 error("handle to closed library"); 488 else if ((dls->module == 0) || (dls->refs == 0))
478 else 489 error("handle to closed library");
479 return TRUE; 490 else
480 return FALSE; 491 return TRUE;
481 } 492 return FALSE;
482 493 }
483 static inline int isFlagSet(int mode, int flag) 494
484 { 495 static inline int
485 return (mode & flag) == flag; 496 isFlagSet(int mode, int flag)
486 } 497 {
487 498 return (mode & flag) == flag;
488 static struct dlstatus *lookupStatus(const struct stat *sbuf) 499 }
489 { 500
490 struct dlstatus *dls = stqueue; 501 static struct dlstatus *
491 debug("looking for status"); 502 lookupStatus(const struct stat *sbuf)
492 while (dls && ( /* isFlagSet(dls->mode, RTLD_UNSHARED) */ 0 503 {
493 || sbuf->st_dev != dls->device || sbuf->st_ino != dls->inode)) 504 struct dlstatus *dls = stqueue;
494 dls = dls->next; 505 debug("looking for status");
495 return dls; 506 while (dls && ( /* isFlagSet(dls->mode, RTLD_UNSHARED) */ 0
496 } 507 || sbuf->st_dev != dls->device
497 508 || sbuf->st_ino != dls->inode))
498 static void insertStatus(struct dlstatus *dls, const struct stat *sbuf) 509 dls = dls->next;
499 { 510 return dls;
500 debug("inserting status"); 511 }
501 dls->inode = sbuf->st_ino; 512
502 dls->device = sbuf->st_dev; 513 static void
503 dls->refs = 0; 514 insertStatus(struct dlstatus *dls, const struct stat *sbuf)
504 dls->mode = 0; 515 {
505 if ((dls->flags & DL_IN_LIST) == 0) 516 debug("inserting status");
506 { 517 dls->inode = sbuf->st_ino;
507 dls->next = stqueue; 518 dls->device = sbuf->st_dev;
508 stqueue = dls; 519 dls->refs = 0;
509 dls->flags |= DL_IN_LIST; 520 dls->mode = 0;
510 } 521 if ((dls->flags & DL_IN_LIST) == 0) {
511 } 522 dls->next = stqueue;
512 523 stqueue = dls;
513 static struct dlstatus *allocStatus() 524 dls->flags |= DL_IN_LIST;
514 { 525 }
515 struct dlstatus *dls; 526 }
527
528 static struct dlstatus *
529 allocStatus()
530 {
531 struct dlstatus *dls;
516 #ifdef REUSE_STATUS 532 #ifdef REUSE_STATUS
517 dls = stqueue; 533 dls = stqueue;
518 while (dls && dls->module) 534 while (dls && dls->module)
519 dls = dls->next; 535 dls = dls->next;
520 if (!dls) 536 if (!dls)
521 #endif 537 #endif
522 dls = SDL_calloc(sizeof(*dls),1); 538 dls = SDL_calloc(sizeof(*dls), 1);
523 return dls; 539 return dls;
524 } 540 }
525 541
526 static int promoteLocalToGlobal(struct dlstatus *dls) 542 static int
527 { 543 promoteLocalToGlobal(struct dlstatus *dls)
528 static int (*p) (NSModule module) = 0; 544 {
529 debug("promoting"); 545 static int (*p) (NSModule module) = 0;
530 if (!p) 546 debug("promoting");
531 _dyld_func_lookup("__dyld_NSMakePrivateModulePublic", (void **)&p); 547 if (!p)
532 return (dls->module == MAGIC_DYLIB_MOD) || (p && p(dls->module)); 548 _dyld_func_lookup("__dyld_NSMakePrivateModulePublic", (void **) &p);
533 } 549 return (dls->module == MAGIC_DYLIB_MOD) || (p && p(dls->module));
534 550 }
535 static void *reference(struct dlstatus *dls, int mode) 551
536 { 552 static void *
537 if (dls) 553 reference(struct dlstatus *dls, int mode)
538 { 554 {
539 if (dls->module == MAGIC_DYLIB_MOD && isFlagSet(mode, RTLD_LOCAL)) 555 if (dls) {
540 { 556 if (dls->module == MAGIC_DYLIB_MOD && isFlagSet(mode, RTLD_LOCAL)) {
541 warning("trying to open a .dylib with RTLD_LOCAL"); 557 warning("trying to open a .dylib with RTLD_LOCAL");
542 error("unable to open a .dylib with RTLD_LOCAL"); 558 error("unable to open a .dylib with RTLD_LOCAL");
543 return NULL; 559 return NULL;
544 } 560 }
545 if (isFlagSet(mode, RTLD_GLOBAL) && 561 if (isFlagSet(mode, RTLD_GLOBAL) && !isFlagSet(dls->mode, RTLD_GLOBAL)
546 !isFlagSet(dls->mode, RTLD_GLOBAL) && !promoteLocalToGlobal(dls)) 562 && !promoteLocalToGlobal(dls)) {
547 { 563 error("unable to promote local module to global");
548 error("unable to promote local module to global"); 564 return NULL;
549 return NULL; 565 }
550 } 566 dls->mode |= mode;
551 dls->mode |= mode; 567 dls->refs++;
552 dls->refs++; 568 } else
553 } 569 debug("reference called with NULL argument");
554 else 570
555 debug("reference called with NULL argument"); 571 return dls;
556 572 }
557 return dls; 573
558 } 574 static const struct mach_header *
559 575 my_find_image(const char *name)
560 static const struct mach_header *my_find_image(const char *name) 576 {
561 { 577 const struct mach_header *mh = 0;
562 const struct mach_header *mh = 0; 578 const char *id = NULL;
563 const char *id = NULL; 579 int i = _dyld_image_count();
564 int i = _dyld_image_count(); 580 int j;
565 int j; 581 mh = (struct mach_header *)
566 mh = (struct mach_header *) 582 dyld_NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED |
567 dyld_NSAddImage(name, NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED | 583 NSADDIMAGE_OPTION_RETURN_ON_ERROR);
568 NSADDIMAGE_OPTION_RETURN_ON_ERROR); 584 if (!mh) {
569 if (!mh) 585 for (j = 0; j < i; j++) {
570 { 586 id = _dyld_get_image_name(j);
571 for (j = 0; j < i; j++) 587 if (!SDL_strcmp(id, name)) {
572 { 588 mh = _dyld_get_image_header(j);
573 id = _dyld_get_image_name(j); 589 break;
574 if (!SDL_strcmp(id, name)) 590 }
575 { 591 }
576 mh = _dyld_get_image_header(j); 592 }
577 break; 593 return mh;
578 }
579 }
580 }
581 return mh;
582 } 594 }
583 595
584 /* 596 /*
585 * dyld adds libraries by first adding the directly dependant libraries in link order, and 597 * 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 598 * 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 599 * 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. 600 * any of it's direct dependencies, then it probably isn't there.
589 */ 601 */
590 static NSSymbol search_linked_libs(const struct mach_header * mh, const char *symbol) 602 static NSSymbol
591 { 603 search_linked_libs(const struct mach_header *mh, const char *symbol)
592 unsigned int n; 604 {
593 struct load_command *lc = 0; 605 unsigned int n;
594 struct mach_header *wh; 606 struct load_command *lc = 0;
595 NSSymbol nssym = 0; 607 struct mach_header *wh;
596 if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage) 608 NSSymbol nssym = 0;
597 { 609 if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage
598 lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); 610 && dyld_NSLookupSymbolInImage) {
599 for (n = 0; n < mh->ncmds; n++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) 611 lc = (struct load_command *) ((char *) mh +
600 { 612 sizeof(struct mach_header));
601 if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd)) 613 for (n = 0; n < mh->ncmds;
602 { 614 n++, lc = (struct load_command *) ((char *) lc + lc->cmdsize)) {
603 if ((wh = (struct mach_header *) 615 if ((LC_LOAD_DYLIB == lc->cmd)
604 my_find_image((char *)(((struct dylib_command *)lc)->dylib.name.offset + 616 || (LC_LOAD_WEAK_DYLIB == lc->cmd)) {
605 (char *)lc)))) 617 if ((wh = (struct mach_header *)
606 { 618 my_find_image((char
607 if (dyld_NSIsSymbolNameDefinedInImage(wh, symbol)) 619 *) (((struct dylib_command *) lc)->
608 { 620 dylib.name.offset + (char *) lc)))) {
609 nssym = dyld_NSLookupSymbolInImage(wh, 621 if (dyld_NSIsSymbolNameDefinedInImage(wh, symbol)) {
610 symbol, 622 nssym = dyld_NSLookupSymbolInImage(wh,
611 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | 623 symbol,
612 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); 624 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
613 break; 625 |
614 } 626 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
615 } 627 break;
616 } 628 }
617 } 629 }
618 if ((!nssym) && NSIsSymbolNameDefined(symbol)) 630 }
619 { 631 }
620 /* I've never seen this debug message...*/ 632 if ((!nssym) && NSIsSymbolNameDefined(symbol)) {
621 debug("Symbol \"%s\" is defined but was not found", symbol); 633 /* I've never seen this debug message... */
622 } 634 debug("Symbol \"%s\" is defined but was not found", symbol);
623 } 635 }
624 return nssym; 636 }
637 return nssym;
625 } 638 }
626 639
627 /* Up to the caller to SDL_free() returned string */ 640 /* Up to the caller to SDL_free() returned string */
628 static inline char *dyld_error_str() 641 static inline char *
629 { 642 dyld_error_str()
630 NSLinkEditErrors dylder; 643 {
631 int dylderno; 644 NSLinkEditErrors dylder;
632 const char *dylderrstr; 645 int dylderno;
633 const char *dyldfile; 646 const char *dylderrstr;
634 char* retStr = NULL; 647 const char *dyldfile;
635 NSLinkEditError(&dylder, &dylderno, &dyldfile, &dylderrstr); 648 char *retStr = NULL;
636 if (dylderrstr && *dylderrstr) 649 NSLinkEditError(&dylder, &dylderno, &dyldfile, &dylderrstr);
637 { 650 if (dylderrstr && *dylderrstr) {
638 retStr = SDL_strdup(dylderrstr); 651 retStr = SDL_strdup(dylderrstr);
639 } 652 }
640 return retStr; 653 return retStr;
641 } 654 }
642 655
643 static void *dlsymIntern(struct dlstatus *dls, const char *symbol, int canSetError) 656 static void *
644 { 657 dlsymIntern(struct dlstatus *dls, const char *symbol, int canSetError)
645 NSSymbol nssym = 0; 658 {
646 #ifdef __GCC__ 659 NSSymbol nssym = 0;
647 void *caller = __builtin_return_address(1); /* Be *very* careful about inlining */ 660 #ifdef __GCC__
661 void *caller = __builtin_return_address(1); /* Be *very* careful about inlining */
648 #else 662 #else
649 void *caller = NULL; 663 void *caller = NULL;
650 #endif 664 #endif
651 const struct mach_header *caller_mh = 0; 665 const struct mach_header *caller_mh = 0;
652 char *savedErrorStr = NULL; 666 char *savedErrorStr = NULL;
653 resetdlerror(); 667 resetdlerror();
654 #ifndef RTLD_SELF 668 #ifndef RTLD_SELF
655 #define RTLD_SELF ((void *) -3) 669 #define RTLD_SELF ((void *) -3)
656 #endif 670 #endif
657 if (NULL == dls) 671 if (NULL == dls)
658 dls = RTLD_SELF; 672 dls = RTLD_SELF;
659 if ((RTLD_NEXT == dls) || (RTLD_SELF == dls)) 673 if ((RTLD_NEXT == dls) || (RTLD_SELF == dls)) {
660 { 674 if (dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage
661 if (dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage && caller) 675 && caller) {
662 { 676 caller_mh = image_for_address(caller);
663 caller_mh = image_for_address(caller); 677 if (RTLD_SELF == dls) {
664 if (RTLD_SELF == dls) 678 /* FIXME: We should be using the NSModule api, if SELF is an MH_BUNDLE
665 { 679 * 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 680 * this is acceptable.
667 * But it appears to work anyway, and looking at the code in dyld_libfuncs.c 681 */
668 * this is acceptable. 682 if (dyld_NSIsSymbolNameDefinedInImage(caller_mh, symbol)) {
669 */ 683 nssym = dyld_NSLookupSymbolInImage(caller_mh,
670 if (dyld_NSIsSymbolNameDefinedInImage(caller_mh, symbol)) 684 symbol,
671 { 685 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
672 nssym = dyld_NSLookupSymbolInImage(caller_mh, 686 |
673 symbol, 687 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
674 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | 688 }
675 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); 689 }
676 } 690 if (!nssym) {
677 } 691 if (RTLD_SELF == dls)
678 if (!nssym) 692 savedErrorStr = dyld_error_str();
679 { 693 nssym = search_linked_libs(caller_mh, symbol);
680 if (RTLD_SELF == dls) 694 }
681 savedErrorStr = dyld_error_str(); 695 } else {
682 nssym = search_linked_libs(caller_mh, symbol); 696 if (canSetError)
683 } 697 error("RTLD_SELF and RTLD_NEXT are not supported");
684 } 698 return NULL;
685 else 699 }
686 { 700 }
687 if (canSetError) 701 if (!nssym) {
688 error("RTLD_SELF and RTLD_NEXT are not supported"); 702
689 return NULL; 703 if (RTLD_DEFAULT == dls) {
690 } 704 dls = &mainStatus;
691 } 705 }
692 if (!nssym) 706 if (!isValidStatus(dls))
693 { 707 return NULL;
694 708
695 if (RTLD_DEFAULT == dls) 709 if (dls->module != MAGIC_DYLIB_MOD) {
696 { 710 nssym = NSLookupSymbolInModule(dls->module, symbol);
697 dls = &mainStatus; 711 if (!nssym && NSIsSymbolNameDefined(symbol)) {
698 } 712 debug("Searching dependencies");
699 if (!isValidStatus(dls)) 713 savedErrorStr = dyld_error_str();
700 return NULL; 714 nssym =
701 715 search_linked_libs(get_mach_header_from_NSModule
702 if (dls->module != MAGIC_DYLIB_MOD) 716 (dls->module), symbol);
703 { 717 }
704 nssym = NSLookupSymbolInModule(dls->module, symbol); 718 } else if (dls->lib && dyld_NSIsSymbolNameDefinedInImage
705 if (!nssym && NSIsSymbolNameDefined(symbol)) 719 && dyld_NSLookupSymbolInImage) {
706 { 720 if (dyld_NSIsSymbolNameDefinedInImage(dls->lib, symbol)) {
707 debug("Searching dependencies"); 721 nssym = dyld_NSLookupSymbolInImage(dls->lib,
708 savedErrorStr = dyld_error_str(); 722 symbol,
709 nssym = search_linked_libs(get_mach_header_from_NSModule(dls->module), symbol); 723 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
710 } 724 |
711 } 725 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
712 else if (dls->lib && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage) 726 } else if (NSIsSymbolNameDefined(symbol)) {
713 { 727 debug("Searching dependencies");
714 if (dyld_NSIsSymbolNameDefinedInImage(dls->lib, symbol)) 728 savedErrorStr = dyld_error_str();
715 { 729 nssym = search_linked_libs(dls->lib, symbol);
716 nssym = dyld_NSLookupSymbolInImage(dls->lib, 730 }
717 symbol, 731 } else if (dls->module == MAGIC_DYLIB_MOD) {
718 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | 732 /* Global context, use NSLookupAndBindSymbol */
719 NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); 733 if (NSIsSymbolNameDefined(symbol)) {
720 } 734 /* There doesn't seem to be a return on error option for this call???
721 else if (NSIsSymbolNameDefined(symbol)) 735 this is potentially broken, if binding fails, it will improperly
722 { 736 exit the application. */
723 debug("Searching dependencies"); 737 nssym = NSLookupAndBindSymbol(symbol);
724 savedErrorStr = dyld_error_str(); 738 } else {
725 nssym = search_linked_libs(dls->lib, symbol); 739 if (savedErrorStr)
726 } 740 SDL_free(savedErrorStr);
727 } 741 savedErrorStr = SDL_malloc(256);
728 else if (dls->module == MAGIC_DYLIB_MOD) 742 SDL_snprintf(savedErrorStr, 256,
729 { 743 "Symbol \"%s\" not in global context", symbol);
730 /* Global context, use NSLookupAndBindSymbol */ 744 }
731 if (NSIsSymbolNameDefined(symbol)) 745 }
732 { 746 }
733 /* There doesn't seem to be a return on error option for this call??? 747 /* Error reporting */
734 this is potentially broken, if binding fails, it will improperly 748 if (!nssym) {
735 exit the application. */ 749 if (!savedErrorStr || !SDL_strlen(savedErrorStr)) {
736 nssym = NSLookupAndBindSymbol(symbol); 750 if (savedErrorStr)
737 } 751 SDL_free(savedErrorStr);
738 else 752 savedErrorStr = SDL_malloc(256);
739 { 753 SDL_snprintf(savedErrorStr, 256, "Symbol \"%s\" not found",
740 if (savedErrorStr) 754 symbol);
741 SDL_free(savedErrorStr); 755 }
742 savedErrorStr = SDL_malloc(256); 756 if (canSetError) {
743 SDL_snprintf(savedErrorStr, 256, "Symbol \"%s\" not in global context",symbol); 757 error(savedErrorStr);
744 } 758 } else {
745 } 759 debug(savedErrorStr);
746 } 760 }
747 /* Error reporting */ 761 if (savedErrorStr)
748 if (!nssym) 762 SDL_free(savedErrorStr);
749 { 763 return NULL;
750 if (!savedErrorStr || !SDL_strlen(savedErrorStr)) 764 }
751 { 765 return NSAddressOfSymbol(nssym);
752 if (savedErrorStr) 766 }
753 SDL_free(savedErrorStr); 767
754 savedErrorStr = SDL_malloc(256); 768 static struct dlstatus *
755 SDL_snprintf(savedErrorStr, 256,"Symbol \"%s\" not found",symbol); 769 loadModule(const char *path, const struct stat *sbuf, int mode)
756 } 770 {
757 if (canSetError) 771 NSObjectFileImage ofi = 0;
758 { 772 NSObjectFileImageReturnCode ofirc;
759 error(savedErrorStr); 773 struct dlstatus *dls;
760 } 774 NSLinkEditErrors ler;
761 else 775 int lerno;
762 { 776 const char *errstr;
763 debug(savedErrorStr); 777 const char *file;
764 } 778 void (*init) (void);
765 if (savedErrorStr) 779
766 SDL_free(savedErrorStr); 780 ofirc = NSCreateObjectFileImageFromFile(path, &ofi);
767 return NULL; 781 switch (ofirc) {
768 } 782 case NSObjectFileImageSuccess:
769 return NSAddressOfSymbol(nssym); 783 break;
770 } 784 case NSObjectFileImageInappropriateFile:
771 785 if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage
772 static struct dlstatus *loadModule(const char *path, const struct stat *sbuf, int mode) 786 && dyld_NSLookupSymbolInImage) {
773 { 787 if (isFlagSet(mode, RTLD_LOCAL)) {
774 NSObjectFileImage ofi = 0; 788 warning("trying to open a .dylib with RTLD_LOCAL");
775 NSObjectFileImageReturnCode ofirc; 789 error("unable to open this file with RTLD_LOCAL");
776 struct dlstatus *dls; 790 return NULL;
777 NSLinkEditErrors ler; 791 }
778 int lerno; 792 } else {
779 const char *errstr; 793 error("opening this file is unsupported on this system");
780 const char *file; 794 return NULL;
781 void (*init) (void); 795 }
782 796 break;
783 ofirc = NSCreateObjectFileImageFromFile(path, &ofi); 797 case NSObjectFileImageFailure:
784 switch (ofirc) 798 error("object file setup failure");
785 { 799 return NULL;
786 case NSObjectFileImageSuccess: 800 case NSObjectFileImageArch:
787 break; 801 error("no object for this architecture");
788 case NSObjectFileImageInappropriateFile: 802 return NULL;
789 if (dyld_NSAddImage && dyld_NSIsSymbolNameDefinedInImage && dyld_NSLookupSymbolInImage) 803 case NSObjectFileImageFormat:
790 { 804 error("bad object file format");
791 if (isFlagSet(mode, RTLD_LOCAL)) 805 return NULL;
792 { 806 case NSObjectFileImageAccess:
793 warning("trying to open a .dylib with RTLD_LOCAL"); 807 error("can't read object file");
794 error("unable to open this file with RTLD_LOCAL"); 808 return NULL;
795 return NULL; 809 default:
796 } 810 error("unknown error from NSCreateObjectFileImageFromFile()");
797 } 811 return NULL;
798 else 812 }
799 { 813 dls = lookupStatus(sbuf);
800 error("opening this file is unsupported on this system"); 814 if (!dls) {
801 return NULL; 815 dls = allocStatus();
802 } 816 }
803 break; 817 if (!dls) {
804 case NSObjectFileImageFailure: 818 error("unable to allocate memory");
805 error("object file setup failure"); 819 return NULL;
806 return NULL; 820 }
807 case NSObjectFileImageArch: 821 // dls->lib = 0;
808 error("no object for this architecture"); 822 if (ofirc == NSObjectFileImageInappropriateFile) {
809 return NULL; 823 if ((dls->lib =
810 case NSObjectFileImageFormat: 824 dyld_NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR))) {
811 error("bad object file format"); 825 debug("Dynamic lib loaded at %ld", dls->lib);
812 return NULL; 826 ofi = MAGIC_DYLIB_OFI;
813 case NSObjectFileImageAccess: 827 dls->module = MAGIC_DYLIB_MOD;
814 error("can't read object file"); 828 ofirc = NSObjectFileImageSuccess;
815 return NULL; 829 /* Although it is possible with a bit of work to modify this so it works and
816 default: 830 functions with RTLD_NOW, I don't deem it necessary at the moment */
817 error("unknown error from NSCreateObjectFileImageFromFile()"); 831 }
818 return NULL; 832 if (!(dls->module)) {
819 } 833 NSLinkEditError(&ler, &lerno, &file, &errstr);
820 dls = lookupStatus(sbuf); 834 if (!errstr || (!SDL_strlen(errstr)))
821 if (!dls) 835 error("Can't open this file type");
822 { 836 else
823 dls = allocStatus(); 837 error(errstr);
824 } 838 if ((dls->flags & DL_IN_LIST) == 0) {
825 if (!dls) 839 SDL_free(dls);
826 { 840 }
827 error("unable to allocate memory"); 841 return NULL;
828 return NULL; 842 }
829 } 843 } else {
830 // dls->lib = 0; 844 dls->module = NSLinkModule(ofi, path,
831 if (ofirc == NSObjectFileImageInappropriateFile) 845 NSLINKMODULE_OPTION_RETURN_ON_ERROR |
832 { 846 NSLINKMODULE_OPTION_PRIVATE |
833 if ((dls->lib = dyld_NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR))) 847 (isFlagSet(mode, RTLD_NOW) ?
834 { 848 NSLINKMODULE_OPTION_BINDNOW : 0));
835 debug("Dynamic lib loaded at %ld", dls->lib); 849 NSDestroyObjectFileImage(ofi);
836 ofi = MAGIC_DYLIB_OFI; 850 if (dls->module) {
837 dls->module = MAGIC_DYLIB_MOD; 851 dls->lib = get_mach_header_from_NSModule(dls->module);
838 ofirc = NSObjectFileImageSuccess; 852 }
839 /* Although it is possible with a bit of work to modify this so it works and 853 }
840 functions with RTLD_NOW, I don't deem it necessary at the moment */ 854 if (!dls->module) {
841 } 855 NSLinkEditError(&ler, &lerno, &file, &errstr);
842 if (!(dls->module)) 856 if ((dls->flags & DL_IN_LIST) == 0) {
843 { 857 SDL_free(dls);
844 NSLinkEditError(&ler, &lerno, &file, &errstr); 858 }
845 if (!errstr || (!SDL_strlen(errstr))) 859 error(errstr);
846 error("Can't open this file type"); 860 return NULL;
847 else 861 }
848 error(errstr); 862
849 if ((dls->flags & DL_IN_LIST) == 0) 863 insertStatus(dls, sbuf);
850 { 864 dls = reference(dls, mode);
851 SDL_free(dls); 865 if ((init = dlsymIntern(dls, "__init", 0))) {
852 } 866 debug("calling _init()");
853 return NULL; 867 init();
854 } 868 }
855 } 869 return dls;
856 else 870 }
857 { 871
858 dls->module = NSLinkModule(ofi, path, 872 inline static void
859 NSLINKMODULE_OPTION_RETURN_ON_ERROR | 873 dlcompat_init_check(void)
860 NSLINKMODULE_OPTION_PRIVATE | 874 {
861 (isFlagSet(mode, RTLD_NOW) ? NSLINKMODULE_OPTION_BINDNOW : 0)); 875 static pthread_mutex_t l = PTHREAD_MUTEX_INITIALIZER;
862 NSDestroyObjectFileImage(ofi); 876 static int init_done = 0;
863 if (dls->module) 877
864 { 878 pthread_mutex_lock(&l);
865 dls->lib = get_mach_header_from_NSModule(dls->module); 879 if (!init_done) {
866 } 880 dlcompat_init_func();
867 } 881 init_done = 1;
868 if (!dls->module) 882 }
869 { 883 pthread_mutex_unlock(&l);
870 NSLinkEditError(&ler, &lerno, &file, &errstr); 884 }
871 if ((dls->flags & DL_IN_LIST) == 0) 885
872 { 886 static void
873 SDL_free(dls); 887 dlcompat_init_func(void)
874 } 888 {
875 error(errstr); 889 _dyld_func_lookup("__dyld_NSAddImage", (void **) &dyld_NSAddImage);
876 return NULL; 890 _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",
877 } 891 (void **) &dyld_NSIsSymbolNameDefinedInImage);
878 892 _dyld_func_lookup("__dyld_NSLookupSymbolInImage",
879 insertStatus(dls, sbuf); 893 (void **) &dyld_NSLookupSymbolInImage);
880 dls = reference(dls, mode); 894 if (pthread_mutex_init(&dlcompat_mutex, NULL))
881 if ((init = dlsymIntern(dls, "__init", 0))) 895 exit(1);
882 { 896 if (pthread_key_create(&dlerror_key, &dlerrorfree))
883 debug("calling _init()"); 897 exit(1);
884 init(); 898 }
885 } 899
886 return dls; 900 static void
887 } 901 resetdlerror()
888 902 {
889 inline static void dlcompat_init_check(void) 903 struct dlthread *tss;
890 { 904 tss = pthread_getspecific(dlerror_key);
891 static pthread_mutex_t l = PTHREAD_MUTEX_INITIALIZER; 905 tss->errset = 0;
892 static int init_done = 0; 906 }
893 907
894 pthread_mutex_lock(&l); 908 static void
895 if (!init_done) { 909 dlerrorfree(void *data)
896 dlcompat_init_func(); 910 {
897 init_done = 1; 911 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 } 912 }
925 913
926 /* We kind of want a recursive lock here, but meet a little trouble 914 /* 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 915 * because they are not available pre OS X 10.2, so we fake it
928 * using thread specific storage to keep a lock count 916 * using thread specific storage to keep a lock count
929 */ 917 */
930 static inline void dolock(void) 918 static inline void
931 { 919 dolock(void)
932 int err = 0; 920 {
933 struct dlthread *tss; 921 int err = 0;
934 dlcompat_init_check(); 922 struct dlthread *tss;
935 tss = pthread_getspecific(dlerror_key); 923 dlcompat_init_check();
936 if (!tss) 924 tss = pthread_getspecific(dlerror_key);
937 { 925 if (!tss) {
938 tss = SDL_malloc(sizeof(struct dlthread)); 926 tss = SDL_malloc(sizeof(struct dlthread));
939 tss->lockcnt = 0; 927 tss->lockcnt = 0;
940 tss->errset = 0; 928 tss->errset = 0;
941 if (pthread_setspecific(dlerror_key, tss)) 929 if (pthread_setspecific(dlerror_key, tss)) {
942 { 930 fprintf(stderr, "dlcompat: pthread_setspecific failed\n");
943 fprintf(stderr,"dlcompat: pthread_setspecific failed\n"); 931 exit(1);
944 exit(1); 932 }
945 } 933 }
946 } 934 if (!tss->lockcnt)
947 if (!tss->lockcnt) 935 err = pthread_mutex_lock(&dlcompat_mutex);
948 err = pthread_mutex_lock(&dlcompat_mutex); 936 tss->lockcnt = tss->lockcnt + 1;
949 tss->lockcnt = tss->lockcnt +1; 937 if (err)
950 if (err) 938 exit(err);
951 exit(err); 939 }
952 } 940
953 941 static inline void
954 static inline void dounlock(void) 942 dounlock(void)
955 { 943 {
956 int err = 0; 944 int err = 0;
957 struct dlthread *tss; 945 struct dlthread *tss;
958 tss = pthread_getspecific(dlerror_key); 946 tss = pthread_getspecific(dlerror_key);
959 tss->lockcnt = tss->lockcnt -1; 947 tss->lockcnt = tss->lockcnt - 1;
960 if (!tss->lockcnt) 948 if (!tss->lockcnt)
961 err = pthread_mutex_unlock(&dlcompat_mutex); 949 err = pthread_mutex_unlock(&dlcompat_mutex);
962 if (err) 950 if (err)
963 exit(err); 951 exit(err);
964 } 952 }
965 953
966 static void *SDL_OSX_dlopen(const char *path, int mode) 954 static void *
967 { 955 SDL_OSX_dlopen(const char *path, int mode)
968 const struct stat *sbuf; 956 {
969 struct dlstatus *dls; 957 const struct stat *sbuf;
970 const char *fullPath; 958 struct dlstatus *dls;
971 959 const char *fullPath;
972 dolock(); 960
973 resetdlerror(); 961 dolock();
974 if (!path) 962 resetdlerror();
975 { 963 if (!path) {
976 dls = &mainStatus; 964 dls = &mainStatus;
977 goto dlopenok; 965 goto dlopenok;
978 } 966 }
979 if (!(sbuf = findFile(path, &fullPath))) 967 if (!(sbuf = findFile(path, &fullPath))) {
980 { 968 error("file \"%s\" not found", path);
981 error("file \"%s\" not found", path); 969 goto dlopenerror;
982 goto dlopenerror; 970 }
983 } 971 /* Now checks that it hasn't been closed already */
984 /* Now checks that it hasn't been closed already */ 972 if ((dls = lookupStatus(sbuf)) && (dls->refs > 0)) {
985 if ((dls = lookupStatus(sbuf)) && (dls->refs > 0)) 973 /* debug("status found"); */
986 { 974 dls = reference(dls, mode);
987 /* debug("status found"); */ 975 goto dlopenok;
988 dls = reference(dls, mode); 976 }
989 goto dlopenok;
990 }
991 #ifdef RTLD_NOLOAD 977 #ifdef RTLD_NOLOAD
992 if (isFlagSet(mode, RTLD_NOLOAD)) 978 if (isFlagSet(mode, RTLD_NOLOAD)) {
993 { 979 error("no existing handle and RTLD_NOLOAD specified");
994 error("no existing handle and RTLD_NOLOAD specified"); 980 goto dlopenerror;
995 goto dlopenerror; 981 }
996 } 982 #endif
997 #endif 983 if (isFlagSet(mode, RTLD_LAZY) && isFlagSet(mode, RTLD_NOW)) {
998 if (isFlagSet(mode, RTLD_LAZY) && isFlagSet(mode, RTLD_NOW)) 984 error("how can I load something both RTLD_LAZY and RTLD_NOW?");
999 { 985 goto dlopenerror;
1000 error("how can I load something both RTLD_LAZY and RTLD_NOW?"); 986 }
1001 goto dlopenerror; 987 dls = loadModule(fullPath, sbuf, mode);
1002 } 988
1003 dls = loadModule(fullPath, sbuf, mode);
1004
1005 dlopenok: 989 dlopenok:
1006 dounlock(); 990 dounlock();
1007 return (void *)dls; 991 return (void *) dls;
1008 dlopenerror: 992 dlopenerror:
1009 dounlock(); 993 dounlock();
1010 return NULL; 994 return NULL;
1011 } 995 }
1012 996
1013 #if !FINK_BUILD 997 #if !FINK_BUILD
1014 static void *SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol) 998 static void *
1015 { 999 SDL_OSX_dlsym(void *dl_restrict handle, const char *dl_restrict symbol)
1016 int sym_len = SDL_strlen(symbol); 1000 {
1017 void *value = NULL; 1001 int sym_len = SDL_strlen(symbol);
1018 char *malloc_sym = NULL; 1002 void *value = NULL;
1019 dolock(); 1003 char *malloc_sym = NULL;
1020 malloc_sym = SDL_malloc(sym_len + 2); 1004 dolock();
1021 if (malloc_sym) 1005 malloc_sym = SDL_malloc(sym_len + 2);
1022 { 1006 if (malloc_sym) {
1023 SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol); 1007 SDL_snprintf(malloc_sym, sym_len + 2, "_%s", symbol);
1024 value = dlsymIntern(handle, malloc_sym, 1); 1008 value = dlsymIntern(handle, malloc_sym, 1);
1025 SDL_free(malloc_sym); 1009 SDL_free(malloc_sym);
1026 } 1010 } else {
1027 else 1011 error("Unable to allocate memory");
1028 { 1012 goto dlsymerror;
1029 error("Unable to allocate memory"); 1013 }
1030 goto dlsymerror; 1014 dounlock();
1031 } 1015 return value;
1032 dounlock();
1033 return value;
1034 dlsymerror: 1016 dlsymerror:
1035 dounlock(); 1017 dounlock();
1036 return NULL; 1018 return NULL;
1037 } 1019 }
1038 #endif 1020 #endif
1039 1021
1040 #if FINK_BUILD 1022 #if FINK_BUILD
1041 1023
1042 static void *dlsym_prepend_underscore(void *handle, const char *symbol) 1024 static void *
1043 { 1025 dlsym_prepend_underscore(void *handle, const char *symbol)
1044 void *answer; 1026 {
1045 dolock(); 1027 void *answer;
1046 answer = dlsym_prepend_underscore_intern(handle, symbol); 1028 dolock();
1047 dounlock(); 1029 answer = dlsym_prepend_underscore_intern(handle, symbol);
1048 return answer; 1030 dounlock();
1049 } 1031 return answer;
1050 1032 }
1051 static void *dlsym_prepend_underscore_intern(void *handle, const char *symbol) 1033
1034 static void *
1035 dlsym_prepend_underscore_intern(void *handle, const char *symbol)
1052 { 1036 {
1053 /* 1037 /*
1054 * A quick and easy way for porting packages which call dlsym(handle,"sym") 1038 * 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 1039 * If the porter adds -Ddlsym=dlsym_prepend_underscore to the CFLAGS then
1056 * this function will be called, and will add the required underscore. 1040 * this function will be called, and will add the required underscore.
1057 * 1041 *
1058 * Note that I haven't figured out yet which should be "standard", prepend 1042 * 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 1043 * the underscore always, or not at all. These global functions need to go away
1060 * for opendarwin. 1044 * for opendarwin.
1061 */ 1045 */
1062 int sym_len = SDL_strlen(symbol); 1046 int sym_len = SDL_strlen(symbol);
1063 void *value = NULL; 1047 void *value = NULL;
1064 char *malloc_sym = NULL; 1048 char *malloc_sym = NULL;
1065 malloc_sym = SDL_malloc(sym_len + 2); 1049 malloc_sym = SDL_malloc(sym_len + 2);
1066 if (malloc_sym) 1050 if (malloc_sym) {
1067 { 1051 SDL_snprintf(malloc_sym, sym_len + 2, "_%s", symbol);
1068 SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol); 1052 value = dlsymIntern(handle, malloc_sym, 1);
1069 value = dlsymIntern(handle, malloc_sym, 1); 1053 SDL_free(malloc_sym);
1070 SDL_free(malloc_sym); 1054 } else {
1071 } 1055 error("Unable to allocate memory");
1072 else 1056 }
1073 { 1057 return value;
1074 error("Unable to allocate memory"); 1058 }
1075 } 1059
1076 return value; 1060 static void *
1077 } 1061 dlsym_auto_underscore(void *handle, const char *symbol)
1078 1062 {
1079 static void *dlsym_auto_underscore(void *handle, const char *symbol) 1063 void *answer;
1080 { 1064 dolock();
1081 void *answer; 1065 answer = dlsym_auto_underscore_intern(handle, symbol);
1082 dolock(); 1066 dounlock();
1083 answer = dlsym_auto_underscore_intern(handle, symbol); 1067 return answer;
1084 dounlock(); 1068
1085 return answer; 1069 }
1086 1070 static void *
1087 } 1071 dlsym_auto_underscore_intern(void *handle, const char *symbol)
1088 static void *dlsym_auto_underscore_intern(void *handle, const char *symbol) 1072 {
1089 { 1073 struct dlstatus *dls = handle;
1090 struct dlstatus *dls = handle; 1074 void *addr = 0;
1091 void *addr = 0; 1075 addr = dlsymIntern(dls, symbol, 0);
1092 addr = dlsymIntern(dls, symbol, 0); 1076 if (!addr)
1093 if (!addr) 1077 addr = dlsym_prepend_underscore_intern(handle, symbol);
1094 addr = dlsym_prepend_underscore_intern(handle, symbol); 1078 return addr;
1095 return addr; 1079 }
1096 } 1080
1097 1081
1098 1082 static void *
1099 static void *SDL_OSX_dlsym(void * dl_restrict handle, const char * dl_restrict symbol) 1083 SDL_OSX_dlsym(void *dl_restrict handle, const char *dl_restrict symbol)
1100 { 1084 {
1101 struct dlstatus *dls = handle; 1085 struct dlstatus *dls = handle;
1102 void *addr = 0; 1086 void *addr = 0;
1103 dolock(); 1087 dolock();
1104 addr = dlsymIntern(dls, symbol, 1); 1088 addr = dlsymIntern(dls, symbol, 1);
1105 dounlock(); 1089 dounlock();
1106 return addr; 1090 return addr;
1107 } 1091 }
1108 #endif 1092 #endif
1109 1093
1110 static int SDL_OSX_dlclose(void *handle) 1094 static int
1111 { 1095 SDL_OSX_dlclose(void *handle)
1112 struct dlstatus *dls = handle; 1096 {
1113 dolock(); 1097 struct dlstatus *dls = handle;
1114 resetdlerror(); 1098 dolock();
1115 if (!isValidStatus(dls)) 1099 resetdlerror();
1116 { 1100 if (!isValidStatus(dls)) {
1117 goto dlcloseerror; 1101 goto dlcloseerror;
1118 } 1102 }
1119 if (dls->module == MAGIC_DYLIB_MOD) 1103 if (dls->module == MAGIC_DYLIB_MOD) {
1120 { 1104 const char *name;
1121 const char *name; 1105 if (!dls->lib) {
1122 if (!dls->lib) 1106 name = "global context";
1123 { 1107 } else {
1124 name = "global context"; 1108 name = get_lib_name(dls->lib);
1125 } 1109 }
1126 else 1110 warning("trying to close a .dylib!");
1127 { 1111 error("Not closing \"%s\" - dynamic libraries cannot be closed",
1128 name = get_lib_name(dls->lib); 1112 name);
1129 } 1113 goto dlcloseerror;
1130 warning("trying to close a .dylib!"); 1114 }
1131 error("Not closing \"%s\" - dynamic libraries cannot be closed", name); 1115 if (!dls->module) {
1132 goto dlcloseerror; 1116 error("module already closed");
1133 } 1117 goto dlcloseerror;
1134 if (!dls->module) 1118 }
1135 { 1119
1136 error("module already closed"); 1120 if (dls->refs == 1) {
1137 goto dlcloseerror; 1121 unsigned long options = 0;
1138 } 1122 void (*fini) (void);
1139 1123 if ((fini = dlsymIntern(dls, "__fini", 0))) {
1140 if (dls->refs == 1) 1124 debug("calling _fini()");
1141 { 1125 fini();
1142 unsigned long options = 0; 1126 }
1143 void (*fini) (void); 1127 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 1128 #ifdef RTLD_NODELETE
1151 if (isFlagSet(dls->mode, RTLD_NODELETE)) 1129 if (isFlagSet(dls->mode, RTLD_NODELETE))
1152 options |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED; 1130 options |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
1153 #endif 1131 #endif
1154 if (!NSUnLinkModule(dls->module, options)) 1132 if (!NSUnLinkModule(dls->module, options)) {
1155 { 1133 error("unable to unlink module");
1156 error("unable to unlink module"); 1134 goto dlcloseerror;
1157 goto dlcloseerror; 1135 }
1158 } 1136 dls->refs--;
1159 dls->refs--; 1137 dls->module = 0;
1160 dls->module = 0; 1138 /* Note: the dlstatus struct dls is neither removed from the list
1161 /* Note: the dlstatus struct dls is neither removed from the list 1139 * 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 1140 * problem in mostly all cases, though.
1163 * problem in mostly all cases, though. 1141 */
1164 */ 1142 }
1165 } 1143 dounlock();
1166 dounlock(); 1144 return 0;
1167 return 0;
1168 dlcloseerror: 1145 dlcloseerror:
1169 dounlock(); 1146 dounlock();
1170 return 1; 1147 return 1;
1171 } 1148 }
1172 1149
1173 static const char *SDL_OSX_dlerror(void) 1150 static const char *
1174 { 1151 SDL_OSX_dlerror(void)
1175 struct dlthread *tss; 1152 {
1176 const char * err_str = NULL; 1153 struct dlthread *tss;
1177 dlcompat_init_check(); 1154 const char *err_str = NULL;
1178 tss = pthread_getspecific(dlerror_key); 1155 dlcompat_init_check();
1179 if (tss != NULL && tss->errset != 0) { 1156 tss = pthread_getspecific(dlerror_key);
1180 tss->errset = 0; 1157 if (tss != NULL && tss->errset != 0) {
1181 err_str = tss->errstr; 1158 tss->errset = 0;
1182 } 1159 err_str = tss->errstr;
1183 return (err_str); 1160 }
1161 return (err_str);
1184 } 1162 }
1185 1163
1186 /* Given an address, return the mach_header for the image containing it 1164 /* 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. 1165 * or zero if the given address is not contained in any loaded images.
1188 */ 1166 */
1189 static const struct mach_header *image_for_address(const void *address) 1167 static const struct mach_header *
1190 { 1168 image_for_address(const void *address)
1191 unsigned long i; 1169 {
1192 unsigned long j; 1170 unsigned long i;
1193 unsigned long count = _dyld_image_count(); 1171 unsigned long j;
1194 const struct mach_header *mh = 0; 1172 unsigned long count = _dyld_image_count();
1195 struct load_command *lc = 0; 1173 const struct mach_header *mh = 0;
1196 unsigned long addr = 0; 1174 struct load_command *lc = 0;
1197 for (i = 0; i < count; i++) 1175 unsigned long addr = 0;
1198 { 1176 for (i = 0; i < count; i++) {
1199 addr = (unsigned long)address - _dyld_get_image_vmaddr_slide(i); 1177 addr = (unsigned long) address - _dyld_get_image_vmaddr_slide(i);
1200 mh = _dyld_get_image_header(i); 1178 mh = _dyld_get_image_header(i);
1201 if (mh) 1179 if (mh) {
1202 { 1180 lc = (struct load_command *) ((char *) mh +
1203 lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); 1181 sizeof(struct mach_header));
1204 for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) 1182 for (j = 0; j < mh->ncmds;
1205 { 1183 j++, lc =
1206 if (LC_SEGMENT == lc->cmd && 1184 (struct load_command *) ((char *) lc + lc->cmdsize)) {
1207 addr >= ((struct segment_command *)lc)->vmaddr && 1185 if (LC_SEGMENT == lc->cmd &&
1208 addr < 1186 addr >= ((struct segment_command *) lc)->vmaddr &&
1209 ((struct segment_command *)lc)->vmaddr + ((struct segment_command *)lc)->vmsize) 1187 addr <
1210 { 1188 ((struct segment_command *) lc)->vmaddr +
1211 goto image_found; 1189 ((struct segment_command *) lc)->vmsize) {
1212 } 1190 goto image_found;
1213 } 1191 }
1214 } 1192 }
1215 mh = 0; 1193 }
1216 } 1194 mh = 0;
1195 }
1217 image_found: 1196 image_found:
1218 return mh; 1197 return mh;
1219 } 1198 }
1220 1199
1221 #if 0 /* unused */ 1200 #if 0 /* unused */
1222 static int SDL_OSX_dladdr(const void * dl_restrict p, SDL_OSX_Dl_info * dl_restrict info) 1201 static int
1202 SDL_OSX_dladdr(const void *dl_restrict p, SDL_OSX_Dl_info * dl_restrict info)
1223 { 1203 {
1224 /* 1204 /*
1225 FIXME: USe the routine image_for_address. 1205 FIXME: USe the routine image_for_address.
1226 */ 1206 */
1227 unsigned long i; 1207 unsigned long i;
1228 unsigned long j; 1208 unsigned long j;
1229 unsigned long count = _dyld_image_count(); 1209 unsigned long count = _dyld_image_count();
1230 struct mach_header *mh = 0; 1210 struct mach_header *mh = 0;
1231 struct load_command *lc = 0; 1211 struct load_command *lc = 0;
1232 unsigned long addr = NULL; 1212 unsigned long addr = NULL;
1233 unsigned long table_off = (unsigned long)0; 1213 unsigned long table_off = (unsigned long) 0;
1234 int found = 0; 1214 int found = 0;
1235 if (!info) 1215 if (!info)
1236 return 0; 1216 return 0;
1237 dolock(); 1217 dolock();
1238 resetdlerror(); 1218 resetdlerror();
1239 info->dli_fname = 0; 1219 info->dli_fname = 0;
1240 info->dli_fbase = 0; 1220 info->dli_fbase = 0;
1241 info->dli_sname = 0; 1221 info->dli_sname = 0;
1242 info->dli_saddr = 0; 1222 info->dli_saddr = 0;
1243 /* Some of this was swiped from code posted by Douglas Davidson <ddavidso AT apple DOT com> 1223 /* 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 1224 * to darwin-development AT lists DOT apple DOT com and slightly modified
1245 */ 1225 */
1246 for (i = 0; i < count; i++) 1226 for (i = 0; i < count; i++) {
1247 { 1227 addr = (unsigned long) p - _dyld_get_image_vmaddr_slide(i);
1248 addr = (unsigned long)p - _dyld_get_image_vmaddr_slide(i); 1228 mh = _dyld_get_image_header(i);
1249 mh = _dyld_get_image_header(i); 1229 if (mh) {
1250 if (mh) 1230 lc = (struct load_command *) ((char *) mh +
1251 { 1231 sizeof(struct mach_header));
1252 lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); 1232 for (j = 0; j < mh->ncmds;
1253 for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) 1233 j++, lc =
1254 { 1234 (struct load_command *) ((char *) lc + lc->cmdsize)) {
1255 if (LC_SEGMENT == lc->cmd && 1235 if (LC_SEGMENT == lc->cmd &&
1256 addr >= ((struct segment_command *)lc)->vmaddr && 1236 addr >= ((struct segment_command *) lc)->vmaddr &&
1257 addr < 1237 addr <
1258 ((struct segment_command *)lc)->vmaddr + ((struct segment_command *)lc)->vmsize) 1238 ((struct segment_command *) lc)->vmaddr +
1259 { 1239 ((struct segment_command *) lc)->vmsize) {
1260 info->dli_fname = _dyld_get_image_name(i); 1240 info->dli_fname = _dyld_get_image_name(i);
1261 info->dli_fbase = (void *)mh; 1241 info->dli_fbase = (void *) mh;
1262 found = 1; 1242 found = 1;
1263 break; 1243 break;
1264 } 1244 }
1265 } 1245 }
1266 if (found) 1246 if (found)
1267 break; 1247 break;
1268 } 1248 }
1269 } 1249 }
1270 if (!found) 1250 if (!found) {
1271 { 1251 dounlock();
1272 dounlock(); 1252 return 0;
1273 return 0; 1253 }
1274 } 1254 lc = (struct load_command *) ((char *) mh + sizeof(struct mach_header));
1275 lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); 1255 for (j = 0; j < mh->ncmds;
1276 for (j = 0; j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) 1256 j++, lc = (struct load_command *) ((char *) lc + lc->cmdsize)) {
1277 { 1257 if (LC_SEGMENT == lc->cmd) {
1278 if (LC_SEGMENT == lc->cmd) 1258 if (!SDL_strcmp
1279 { 1259 (((struct segment_command *) lc)->segname, "__LINKEDIT"))
1280 if (!SDL_strcmp(((struct segment_command *)lc)->segname, "__LINKEDIT")) 1260 break;
1281 break; 1261 }
1282 } 1262 }
1283 } 1263 table_off =
1284 table_off = 1264 ((unsigned long) ((struct segment_command *) lc)->vmaddr) -
1285 ((unsigned long)((struct segment_command *)lc)->vmaddr) - 1265 ((unsigned long) ((struct segment_command *) lc)->fileoff) +
1286 ((unsigned long)((struct segment_command *)lc)->fileoff) + _dyld_get_image_vmaddr_slide(i); 1266 _dyld_get_image_vmaddr_slide(i);
1287 debug("table off %x", table_off); 1267 debug("table off %x", table_off);
1288 1268
1289 lc = (struct load_command *)((char *)mh + sizeof(struct mach_header)); 1269 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)) 1270 for (j = 0; j < mh->ncmds;
1291 { 1271 j++, lc = (struct load_command *) ((char *) lc + lc->cmdsize)) {
1292 if (LC_SYMTAB == lc->cmd) 1272 if (LC_SYMTAB == lc->cmd) {
1293 { 1273
1294 1274 struct nlist *symtable =
1295 struct nlist *symtable = (struct nlist *)(((struct symtab_command *)lc)->symoff + table_off); 1275 (struct nlist *) (((struct symtab_command *) lc)->symoff +
1296 unsigned long numsyms = ((struct symtab_command *)lc)->nsyms; 1276 table_off);
1297 struct nlist *nearest = NULL; 1277 unsigned long numsyms = ((struct symtab_command *) lc)->nsyms;
1298 unsigned long diff = 0xffffffff; 1278 struct nlist *nearest = NULL;
1299 unsigned long strtable = (unsigned long)(((struct symtab_command *)lc)->stroff + table_off); 1279 unsigned long diff = 0xffffffff;
1300 debug("symtable %x", symtable); 1280 unsigned long strtable =
1301 for (i = 0; i < numsyms; i++) 1281 (unsigned long) (((struct symtab_command *) lc)->stroff +
1302 { 1282 table_off);
1303 /* Ignore the following kinds of Symbols */ 1283 debug("symtable %x", symtable);
1304 if ((!symtable->n_value) /* Undefined */ 1284 for (i = 0; i < numsyms; i++) {
1305 || (symtable->n_type >= N_PEXT) /* Debug symbol */ 1285 /* Ignore the following kinds of Symbols */
1306 || (!(symtable->n_type & N_EXT)) /* Local Symbol */ 1286 if ((!symtable->n_value) /* Undefined */
1307 ) 1287 ||(symtable->n_type >= N_PEXT) /* Debug symbol */
1308 { 1288 ||(!(symtable->n_type & N_EXT)) /* Local Symbol */
1309 symtable++; 1289 ) {
1310 continue; 1290 symtable++;
1311 } 1291 continue;
1312 if ((addr >= symtable->n_value) && (diff >= (symtable->n_value - addr))) 1292 }
1313 { 1293 if ((addr >= symtable->n_value)
1314 diff = (unsigned long)symtable->n_value - addr; 1294 && (diff >= (symtable->n_value - addr))) {
1315 nearest = symtable; 1295 diff = (unsigned long) symtable->n_value - addr;
1316 } 1296 nearest = symtable;
1317 symtable++; 1297 }
1318 } 1298 symtable++;
1319 if (nearest) 1299 }
1320 { 1300 if (nearest) {
1321 info->dli_saddr = nearest->n_value + ((void *)p - addr); 1301 info->dli_saddr = nearest->n_value + ((void *) p - addr);
1322 info->dli_sname = (char *)(strtable + nearest->n_un.n_strx); 1302 info->dli_sname = (char *) (strtable + nearest->n_un.n_strx);
1323 } 1303 }
1324 } 1304 }
1325 } 1305 }
1326 dounlock(); 1306 dounlock();
1327 return 1; 1307 return 1;
1328 } 1308 }
1329 #endif 1309 #endif
1330 1310
1331 /* 1311 /*
1332 * Implement the dlfunc() interface, which behaves exactly the same as 1312 * Implement the dlfunc() interface, which behaves exactly the same as
1335 * about undefined behavior, and is intended as prior art for future 1315 * about undefined behavior, and is intended as prior art for future
1336 * POSIX standardization. This function requires that all pointer types 1316 * POSIX standardization. This function requires that all pointer types
1337 * have the same representation, which is true on all platforms FreeBSD 1317 * have the same representation, which is true on all platforms FreeBSD
1338 * runs on, but is not guaranteed by the C standard. 1318 * runs on, but is not guaranteed by the C standard.
1339 */ 1319 */
1340 #if 0 1320 #if 0
1341 static dlfunc_t SDL_OSX_dlfunc(void * dl_restrict handle, const char * dl_restrict symbol) 1321 static dlfunc_t
1342 { 1322 SDL_OSX_dlfunc(void *dl_restrict handle, const char *dl_restrict symbol)
1343 union 1323 {
1344 { 1324 union
1345 void *d; 1325 {
1346 dlfunc_t f; 1326 void *d;
1347 } rv; 1327 dlfunc_t f;
1348 int sym_len = SDL_strlen(symbol); 1328 } rv;
1349 char *malloc_sym = NULL; 1329 int sym_len = SDL_strlen(symbol);
1350 dolock(); 1330 char *malloc_sym = NULL;
1351 malloc_sym = SDL_malloc(sym_len + 2); 1331 dolock();
1352 if (malloc_sym) 1332 malloc_sym = SDL_malloc(sym_len + 2);
1353 { 1333 if (malloc_sym) {
1354 SDL_snprintf(malloc_sym, sym_len+2, "_%s", symbol); 1334 SDL_snprintf(malloc_sym, sym_len + 2, "_%s", symbol);
1355 rv.d = dlsymIntern(handle, malloc_sym, 1); 1335 rv.d = dlsymIntern(handle, malloc_sym, 1);
1356 SDL_free(malloc_sym); 1336 SDL_free(malloc_sym);
1357 } 1337 } else {
1358 else 1338 error("Unable to allocate memory");
1359 { 1339 goto dlfuncerror;
1360 error("Unable to allocate memory"); 1340 }
1361 goto dlfuncerror; 1341 dounlock();
1362 } 1342 return rv.f;
1363 dounlock();
1364 return rv.f;
1365 dlfuncerror: 1343 dlfuncerror:
1366 dounlock(); 1344 dounlock();
1367 return NULL; 1345 return NULL;
1368 } 1346 }
1369 #endif 1347 #endif
1370 1348
1371 1349
1372 1350
1376 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1354 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1377 /* System dependent library loading routines */ 1355 /* System dependent library loading routines */
1378 1356
1379 #include "SDL_loadso.h" 1357 #include "SDL_loadso.h"
1380 1358
1381 void *SDL_LoadObject(const char *sofile) 1359 void *
1382 { 1360 SDL_LoadObject(const char *sofile)
1383 void *handle = SDL_OSX_dlopen(sofile, RTLD_NOW); 1361 {
1384 const char *loaderror = SDL_OSX_dlerror(); 1362 void *handle = SDL_OSX_dlopen(sofile, RTLD_NOW);
1385 if ( handle == NULL ) { 1363 const char *loaderror = SDL_OSX_dlerror();
1386 SDL_SetError("Failed loading %s: %s", sofile, loaderror); 1364 if (handle == NULL) {
1387 } 1365 SDL_SetError("Failed loading %s: %s", sofile, loaderror);
1388 return(handle); 1366 }
1389 } 1367 return (handle);
1390 1368 }
1391 void *SDL_LoadFunction(void *handle, const char *name) 1369
1392 { 1370 void *
1393 void *symbol = SDL_OSX_dlsym(handle, name); 1371 SDL_LoadFunction(void *handle, const char *name)
1394 if ( symbol == NULL ) { 1372 {
1395 SDL_SetError("Failed loading %s: %s", name, SDL_OSX_dlerror()); 1373 void *symbol = SDL_OSX_dlsym(handle, name);
1396 } 1374 if (symbol == NULL) {
1397 return(symbol); 1375 SDL_SetError("Failed loading %s: %s", name, SDL_OSX_dlerror());
1398 } 1376 }
1399 1377 return (symbol);
1400 void SDL_UnloadObject(void *handle) 1378 }
1401 { 1379
1402 if ( handle != NULL ) { 1380 void
1403 SDL_OSX_dlclose(handle); 1381 SDL_UnloadObject(void *handle)
1404 } 1382 {
1383 if (handle != NULL) {
1384 SDL_OSX_dlclose(handle);
1385 }
1405 } 1386 }
1406 1387
1407 #endif /* SDL_LOADSO_DLCOMPAT */ 1388 #endif /* SDL_LOADSO_DLCOMPAT */
1389 /* vi: set ts=4 sw=4 expandtab: */